From 4999fa4686f6f9dcb363b169f4657c89cef4d255 Mon Sep 17 00:00:00 2001 From: Aliaksei Urbanski Date: Wed, 9 Oct 2019 06:52:03 +0300 Subject: [PATCH] Add test coverage collecting I believe that we should be able to see the test coverage. These changes: - make tests use pytest - add displaying of the test coverage - add sending of collected coverage data to https://codecov.io --- .coveragerc | 4 ++ .gitignore | 1 + .travis.yml | 4 ++ coverage.sh | 29 +++++++++++ .../ext/jaeger/gen/agent/Agent.py | 8 +-- .../ext/jaeger/gen/agent/ttypes.py | 9 ++-- .../opentelemetry/context/async_context.py | 52 ++++++++++--------- pytest-cov.ini | 6 +++ pytest.ini | 2 + tox.ini | 17 +++++- 10 files changed, 98 insertions(+), 34 deletions(-) create mode 100644 .coveragerc create mode 100755 coverage.sh create mode 100644 pytest-cov.ini create mode 100644 pytest.ini diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000000..a00b3844cae --- /dev/null +++ b/.coveragerc @@ -0,0 +1,4 @@ +[run] +omit = + */tests/* + */setup.py diff --git a/.gitignore b/.gitignore index 679b6fd0ccf..6d74223a167 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ venv*/ pip-log.txt # Unit test / coverage reports +coverage.xml .coverage .nox .tox diff --git a/.travis.yml b/.travis.yml index 64eebc36213..f8c01c80be7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,3 +19,7 @@ install: script: - tox + +after_success: + - pip install codecov + - codecov -v diff --git a/coverage.sh b/coverage.sh new file mode 100755 index 00000000000..51bd4634b39 --- /dev/null +++ b/coverage.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +function cov { + pytest ${1} \ + -c pytest-cov.ini \ + --ignore-glob=*/setup.py \ + --cov opentelemetry-api \ + --cov opentelemetry-sdk \ + --cov ext \ + --cov examples \ + --cov-append \ + --cov-branch \ + --cov-report= +} + + +coverage erase + +cov opentelemetry-api +cov opentelemetry-sdk +cov ext/opentelemetry-ext-http-requests +cov ext/opentelemetry-ext-jaeger +cov ext/opentelemetry-ext-wsgi +cov examples/opentelemetry-example-app + +coverage report +coverage xml diff --git a/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/agent/Agent.py b/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/agent/Agent.py index e8e0fe662ed..b8fac11a5c2 100644 --- a/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/agent/Agent.py +++ b/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/agent/Agent.py @@ -124,7 +124,7 @@ class emitZipkinBatch_args(object): thrift_spec = ( None, # 0 - (1, TType.LIST, 'spans', (TType.STRUCT, (zipkincore.ttypes.Span, zipkincore.ttypes.Span.thrift_spec), False), None, ), # 1 + (1, TType.LIST, 'spans', (TType.STRUCT, (zipkincore_ttypes.Span, zipkincore_ttypes.Span.thrift_spec), False), None, ), # 1 ) def __init__(self, spans=None,): @@ -144,7 +144,7 @@ def read(self, iprot): self.spans = [] (_etype3, _size0) = iprot.readListBegin() for _i4 in range(_size0): - _elem5 = zipkincore.ttypes.Span() + _elem5 = zipkincore_ttypes.Span() _elem5.read(iprot) self.spans.append(_elem5) iprot.readListEnd() @@ -193,7 +193,7 @@ class emitBatch_args(object): thrift_spec = ( None, # 0 - (1, TType.STRUCT, 'batch', (jaeger.ttypes.Batch, jaeger.ttypes.Batch.thrift_spec), None, ), # 1 + (1, TType.STRUCT, 'batch', (jaeger_ttypes.Batch, jaeger_ttypes.Batch.thrift_spec), None, ), # 1 ) def __init__(self, batch=None,): @@ -210,7 +210,7 @@ def read(self, iprot): break if fid == 1: if ftype == TType.STRUCT: - self.batch = jaeger.ttypes.Batch() + self.batch = jaeger_ttypes.Batch() self.batch.read(iprot) else: iprot.skip(ftype) diff --git a/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/agent/ttypes.py b/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/agent/ttypes.py index fc8743cba9f..461c414f53a 100644 --- a/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/agent/ttypes.py +++ b/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/agent/ttypes.py @@ -6,10 +6,11 @@ # options string: py # -from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException -from thrift.protocol.TProtocol import TProtocolException import sys -import jaeger.ttypes -import zipkincore.ttypes +from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException +from thrift.protocol.TProtocol import TProtocolException from thrift.transport import TTransport + +from ..jaeger import ttypes as jaeger_ttypes +from ..zipkincore import ttypes as zipkincore_ttypes diff --git a/opentelemetry-api/src/opentelemetry/context/async_context.py b/opentelemetry-api/src/opentelemetry/context/async_context.py index e7337d103f0..9ff83c98ab6 100644 --- a/opentelemetry-api/src/opentelemetry/context/async_context.py +++ b/opentelemetry-api/src/opentelemetry/context/async_context.py @@ -12,32 +12,34 @@ # See the License for the specific language governing permissions and # limitations under the License. -import typing # pylint: disable=unused-import -from contextvars import ContextVar +try: + from contextvars import ContextVar +except ImportError: + pass +else: + import typing # pylint: disable=unused-import + from . import base_context -from . import base_context + class AsyncRuntimeContext(base_context.BaseRuntimeContext): + class Slot(base_context.BaseRuntimeContext.Slot): + def __init__(self, name: str, default: "object"): + # pylint: disable=super-init-not-called + self.name = name + self.contextvar = ContextVar(name) # type: ContextVar[object] + self.default = base_context.wrap_callable( + default + ) # type: typing.Callable[..., object] + def clear(self) -> None: + self.contextvar.set(self.default()) -class AsyncRuntimeContext(base_context.BaseRuntimeContext): - class Slot(base_context.BaseRuntimeContext.Slot): - def __init__(self, name: str, default: "object"): - # pylint: disable=super-init-not-called - self.name = name - self.contextvar = ContextVar(name) # type: ContextVar[object] - self.default = base_context.wrap_callable( - default - ) # type: typing.Callable[..., object] + def get(self) -> "object": + try: + return self.contextvar.get() + except LookupError: + value = self.default() + self.set(value) + return value - def clear(self) -> None: - self.contextvar.set(self.default()) - - def get(self) -> "object": - try: - return self.contextvar.get() - except LookupError: - value = self.default() - self.set(value) - return value - - def set(self, value: "object") -> None: - self.contextvar.set(value) + def set(self, value: "object") -> None: + self.contextvar.set(value) diff --git a/pytest-cov.ini b/pytest-cov.ini new file mode 100644 index 00000000000..d34438e8c3b --- /dev/null +++ b/pytest-cov.ini @@ -0,0 +1,6 @@ +[pytest] +addopts = -rs -v + +# We need this to make pytest "touch" every python file +# in order to include them into the coverage report. +python_files = *.py diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000000..a71d000b560 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = -rs -v diff --git a/tox.ini b/tox.ini index 0db2364f197..c6b27645851 100644 --- a/tox.ini +++ b/tox.ini @@ -4,6 +4,8 @@ skip_missing_interpreters = True envlist = py3{4,5,6,7,8}-test-{api,sdk,example-app,ext-wsgi,ext-http-requests,ext-jaeger} pypy3-test-{api,sdk,example-app,ext-wsgi,ext-http-requests,ext-jaeger} + py3{4,5,6,7,8}-coverage + pypy3-coverage lint py37-{mypy,mypyinstalled} docs @@ -14,6 +16,8 @@ python = [testenv] deps = + test: pytest + coverage: pytest-cov mypy,mypyinstalled: mypy~=0.711 setenv = @@ -42,12 +46,23 @@ commands_pre = jaeger: pip install {toxinidir}/opentelemetry-sdk jaeger: pip install {toxinidir}/ext/opentelemetry-ext-jaeger +; In order to get a healthy coverage report, +; we have to install packages in editable mode. + coverage: pip install -e {toxinidir}/opentelemetry-api + coverage: pip install -e {toxinidir}/opentelemetry-sdk + coverage: pip install -e {toxinidir}/ext/opentelemetry-ext-azure-monitor + coverage: pip install -e {toxinidir}/ext/opentelemetry-ext-http-requests + coverage: pip install -e {toxinidir}/ext/opentelemetry-ext-jaeger + coverage: pip install -e {toxinidir}/ext/opentelemetry-ext-wsgi + coverage: pip install -e {toxinidir}/examples/opentelemetry-example-app + ; Using file:// here because otherwise tox invokes just "pip install ; opentelemetry-api", leading to an error mypyinstalled: pip install file://{toxinidir}/opentelemetry-api/ commands = - test: python -m unittest discover + test: pytest + coverage: {toxinidir}/coverage.sh mypy: mypy --namespace-packages opentelemetry-api/src/opentelemetry/ ; For test code, we don't want to enforce the full mypy strictness