Migrate to ostestr framework and PY3

Following commits does several things:

* migrates CI of monasca-common to ostestr
* enables PY35 compatybility

Also:

* marked one tests as excluded under PY35 because changing
it would require affecting embedded kafka library which
will be eventually removed in future

Change-Id: I432a466e2620bc8d305ef2630307b636461c8e81
This commit is contained in:
Tomasz Trębski 2017-01-13 11:01:47 +01:00
parent 43bcfeed99
commit cabc2ddd5f
13 changed files with 228 additions and 96 deletions

7
.coveragerc Normal file
View File

@ -0,0 +1,7 @@
[run]
branch = True
source = monasca_common
omit = monasca_common/tests/*
[report]
ignore_errors = True

3
.gitignore vendored
View File

@ -16,3 +16,6 @@ build
dist dist
*.egg-info *.egg-info
*.egg *.egg
cover/
.coverage
.testrepository/

9
.testr.conf Normal file
View File

@ -0,0 +1,9 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-160} \
${PYTHON:-python} -m subunit.run discover -t ./ $OS_TEST_PATH $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list
group_regex=monasca_common\.tests(?:\.|_)([^_]+)

View File

@ -11,7 +11,8 @@
# under the License. # under the License.
import mock import mock
import unittest
from oslotest import base
from monasca_common.kafka import consumer from monasca_common.kafka import consumer
from monasca_common.kafka import producer from monasca_common.kafka import producer
@ -24,9 +25,11 @@ FAKE_KAFKA_CONSUMER_GROUP = "group"
FAKE_KAFKA_TOPIC = "topic" FAKE_KAFKA_TOPIC = "topic"
class TestKafkaProducer(unittest.TestCase): class TestKafkaProducer(base.BaseTestCase):
def setUp(self): def setUp(self):
super(TestKafkaProducer, self).setUp()
self.kafka_client_patcher = mock.patch('monasca_common.kafka.producer.kafka_client') self.kafka_client_patcher = mock.patch('monasca_common.kafka.producer.kafka_client')
self.kafka_producer_patcher = mock.patch('monasca_common.kafka.producer.kafka_producer') self.kafka_producer_patcher = mock.patch('monasca_common.kafka.producer.kafka_producer')
self.mock_kafka_client = self.kafka_client_patcher.start() self.mock_kafka_client = self.kafka_client_patcher.start()
@ -36,6 +39,8 @@ class TestKafkaProducer(unittest.TestCase):
self.monasca_kafka_producer = producer.KafkaProducer(FAKE_KAFKA_URL) self.monasca_kafka_producer = producer.KafkaProducer(FAKE_KAFKA_URL)
def tearDown(self): def tearDown(self):
super(TestKafkaProducer, self).tearDown()
self.kafka_producer_patcher.stop() self.kafka_producer_patcher.stop()
self.kafka_client_patcher.stop() self.kafka_client_patcher.stop()
@ -83,9 +88,11 @@ class TestKafkaProducer(unittest.TestCase):
'Error publishing to {} topic.'. format(topic)) 'Error publishing to {} topic.'. format(topic))
class TestKafkaConsumer(unittest.TestCase): class TestKafkaConsumer(base.BaseTestCase):
def setUp(self): def setUp(self):
super(TestKafkaConsumer, self).setUp()
self.kafka_client_patcher = mock.patch('monasca_common.kafka.consumer.kafka_client') self.kafka_client_patcher = mock.patch('monasca_common.kafka.consumer.kafka_client')
self.kafka_common_patcher = mock.patch('monasca_common.kafka.consumer.kafka_common') self.kafka_common_patcher = mock.patch('monasca_common.kafka.consumer.kafka_common')
self.kafka_consumer_patcher = mock.patch('monasca_common.kafka.consumer.kafka_consumer') self.kafka_consumer_patcher = mock.patch('monasca_common.kafka.consumer.kafka_consumer')
@ -105,6 +112,8 @@ class TestKafkaConsumer(unittest.TestCase):
FAKE_KAFKA_CONSUMER_GROUP, FAKE_KAFKA_TOPIC) FAKE_KAFKA_CONSUMER_GROUP, FAKE_KAFKA_TOPIC)
def tearDown(self): def tearDown(self):
super(TestKafkaConsumer, self).tearDown()
self.kafka_client_patcher.stop() self.kafka_client_patcher.stop()
self.kafka_common_patcher.stop() self.kafka_common_patcher.stop()
self.kafka_consumer_patcher.stop() self.kafka_consumer_patcher.stop()
@ -143,7 +152,7 @@ class TestKafkaConsumer(unittest.TestCase):
try: try:
list(self.monasca_kafka_consumer) list(self.monasca_kafka_consumer)
except Exception as e: except Exception as e:
self.assertEqual(e.message, "Failed to acquire partition") self.assertEqual(str(e), "Failed to acquire partition")
@mock.patch('monasca_common.kafka.consumer.SetPartitioner') @mock.patch('monasca_common.kafka.consumer.SetPartitioner')
def test_kafka_consumer_reset_when_offset_out_of_range( def test_kafka_consumer_reset_when_offset_out_of_range(

View File

@ -10,22 +10,24 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import unittest
import mock import mock
from oslotest import base
import monasca_common.repositories.exceptions as exceptions import monasca_common.repositories.exceptions as exceptions
from monasca_common.repositories.mysql import mysql_repository from monasca_common.repositories.mysql import mysql_repository
class TestMySQLRepository(unittest.TestCase): class TestMySQLRepository(base.BaseTestCase):
def setUp(self): def setUp(self):
super(TestMySQLRepository, self).setUp()
self.cfg_patcher = mock.patch('oslo_config.cfg.CONF') self.cfg_patcher = mock.patch('oslo_config.cfg.CONF')
self.mock_cfg = self.cfg_patcher.start() self.mock_cfg = self.cfg_patcher.start()
def tearDown(self): def tearDown(self):
super(TestMySQLRepository, self).tearDown()
self.cfg_patcher.stop() self.cfg_patcher.stop()
def test_init(self): def test_init(self):

View File

@ -11,19 +11,22 @@
# under the License. # under the License.
import mock import mock
import unittest
from oslotest import base
from monasca_common.rest import exceptions from monasca_common.rest import exceptions
from monasca_common.rest import utils from monasca_common.rest import utils
class TestRestUtils(unittest.TestCase): class TestRestUtils(base.BaseTestCase):
def setUp(self): def setUp(self):
super(TestRestUtils, self).setUp()
self.mock_json_patcher = mock.patch('monasca_common.rest.utils.json') self.mock_json_patcher = mock.patch('monasca_common.rest.utils.json')
self.mock_json = self.mock_json_patcher.start() self.mock_json = self.mock_json_patcher.start()
def tearDown(self): def tearDown(self):
super(TestRestUtils, self).tearDown()
self.mock_json_patcher.stop() self.mock_json_patcher.stop()
def test_read_body_with_success(self): def test_read_body_with_success(self):

View File

@ -13,8 +13,11 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import os
import sys import sys
import unittest
from oslotest import base
import six
import monasca_common.simport.simport as simport import monasca_common.simport.simport as simport
@ -34,7 +37,11 @@ class LocalClass(object):
pass pass
class TestSimport(unittest.TestCase): PWD = os.path.dirname(os.path.abspath(__file__))
class TestSimport(base.BaseTestCase):
def test_bad_targets(self): def test_bad_targets(self):
self.assertRaises(simport.BadDirectory, simport._get_module, self.assertRaises(simport.BadDirectory, simport._get_module,
"|foo.Class") "|foo.Class")
@ -51,30 +58,78 @@ class TestSimport(unittest.TestCase):
self.assertFalse("AnyModuleName" in sys.modules) self.assertFalse("AnyModuleName" in sys.modules)
self.assertRaises(simport.MissingMethodOrFunction, simport._get_module, self.assertRaises(simport.MissingMethodOrFunction, simport._get_module,
"tests|AnyModuleName:") PWD + "|AnyModuleName:")
self.assertFalse("AnyModuleName" in sys.modules) self.assertFalse("AnyModuleName" in sys.modules)
def test_good_external_targets(self): def test_good_external_targets(self):
self.assertEqual(("localmodule", "Foo", "method_a"), self.assertEqual(("localmodule", "Foo", "method_a"),
simport._get_module("tests|" simport._get_module(PWD + "|localmodule:Foo.method_a"))
"localmodule:Foo.method_a"))
self.assertRaises(simport.ImportFailed, simport._get_module, self.assertRaises(simport.ImportFailed, simport._get_module,
"tests|that_module:function_a") PWD + "|that_module:function_a")
def test_bad_load(self): def test_bad_load(self):
self.assertRaises(AttributeError, simport.load, self.assertRaises(simport.ImportFailed, simport.load,
"TestSimport:missing") "TestSimport:missing")
def test_good_load_internal(self): def test_good_load_internal(self):
self.assertEqual(dummy_function, self.assertEqual(six.get_function_code(dummy_function),
simport.load("TestSimport:dummy_function")) six.get_function_code(simport.load("test_simport:dummy_function")))
self.assertEqual(DummyClass.method_a, self.assertEqual(six.get_function_code(DummyClass.method_a),
simport.load("TestSimport:DummyClass.method_a")) six.get_function_code(simport.load("test_simport:DummyClass.method_a")))
def test_local_class(self):
klass = simport.load("LocalClass", __name__)
self.assertEqual(klass, LocalClass)
# Check python versions for importing modules.
# Python 2 import modules with full path to this module as a module name,
# for example:
# <module 'monasca_common.tests.external.externalmodule' from
# 'full_path/monasca-common/monasca_common/tests/external/externalmodule.py'>
#
# while Python 3:
# <module 'external.externalmodule' from 'full_path/monasca-common/monasca_common/tests/external/externalmodule.py'>
# , that's why we need to provide different module names for simport in Python 2 and 3
#
if six.PY2:
class TestSimportPY2(base.BaseTestCase):
def test_good_load_local(self): def test_good_load_local(self):
method = simport.load("tests|" method = simport.load(PWD + "|monasca_common.tests.localmodule:Foo.method_a")
"localmodule:Foo.method_a") import localmodule
self.assertEqual(method, localmodule.Foo.method_a)
self.assertEqual(localmodule.function_a,
simport.load("monasca_common.tests.localmodule:function_a"))
def test_good_load_external(self):
method = simport.load(PWD + "/external|monasca_common.tests.external.externalmodule:Blah.method_b")
self.assertTrue('monasca_common.tests.external.externalmodule' in sys.modules)
old = sys.modules['monasca_common.tests.external.externalmodule']
import external.externalmodule
self.assertEqual(external.externalmodule,
sys.modules['monasca_common.tests.external.externalmodule'])
self.assertEqual(old, external.externalmodule)
self.assertEqual(method, external.externalmodule.Blah.method_b)
def test_import_class(self):
klass = simport.load(PWD + "/external|monasca_common.tests.external.externalmodule:Blah")
import external.externalmodule
self.assertEqual(klass, external.externalmodule.Blah)
elif six.PY3:
class TestSimportPY3(base.BaseTestCase):
def test_good_load_local(self):
method = simport.load(PWD + "|localmodule:Foo.method_a")
import localmodule import localmodule
self.assertEqual(method, localmodule.Foo.method_a) self.assertEqual(method, localmodule.Foo.method_a)
@ -82,8 +137,8 @@ class TestSimport(unittest.TestCase):
simport.load("localmodule:function_a")) simport.load("localmodule:function_a"))
def test_good_load_external(self): def test_good_load_external(self):
method = simport.load("tests/external|"
"external.externalmodule:Blah.method_b") method = simport.load(PWD + "/external|external.externalmodule:Blah.method_b")
self.assertTrue('external.externalmodule' in sys.modules) self.assertTrue('external.externalmodule' in sys.modules)
old = sys.modules['external.externalmodule'] old = sys.modules['external.externalmodule']
@ -95,12 +150,7 @@ class TestSimport(unittest.TestCase):
self.assertEqual(method, external.externalmodule.Blah.method_b) self.assertEqual(method, external.externalmodule.Blah.method_b)
def test_import_class(self): def test_import_class(self):
klass = simport.load("tests/external|" klass = simport.load(PWD + "/external|external.externalmodule:Blah")
"external.externalmodule:Blah")
import external.externalmodule import external.externalmodule
self.assertEqual(klass, external.externalmodule.Blah) self.assertEqual(klass, external.externalmodule.Blah)
def test_local_class(self):
klass = simport.load("LocalClass", __name__)
self.assertEqual(klass, LocalClass)

View File

@ -13,9 +13,10 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import monasca_common.validation.metrics as metric_validator from oslotest import base
from six.moves import range import six
import unittest
from monasca_common.validation import metrics as metric_validator
# a few valid characters to test # a few valid characters to test
valid_name_chars = ".'_-" valid_name_chars = ".'_-"
@ -26,7 +27,7 @@ valid_dimension_chars = " .'_-"
invalid_dimension_chars = "<>={}(),\"\\\\;&" invalid_dimension_chars = "<>={}(),\"\\\\;&"
class TestMetricValidation(unittest.TestCase): class TestMetricValidation(base.BaseTestCase):
def test_valid_single_metric(self): def test_valid_single_metric(self):
metric = {"name": "test_metric_name", metric = {"name": "test_metric_name",
"dimensions": {"key1": "value1", "dimensions": {"key1": "value1",
@ -55,19 +56,19 @@ class TestMetricValidation(unittest.TestCase):
def test_valid_metric_unicode_dimension_value(self): def test_valid_metric_unicode_dimension_value(self):
metric = {"name": "test_metric_name", metric = {"name": "test_metric_name",
"timestamp": 1405630174123, "timestamp": 1405630174123,
"dimensions": {unichr(2440): 'B', 'B': 'C', 'D': 'E'}, "dimensions": {six.unichr(2440): 'B', 'B': 'C', 'D': 'E'},
"value": 5} "value": 5}
metric_validator.validate(metric) metric_validator.validate(metric)
def test_valid_metric_unicode_dimension_key(self): def test_valid_metric_unicode_dimension_key(self):
metric = {"name": 'test_metric_name', metric = {"name": 'test_metric_name',
"dimensions": {'A': 'B', 'B': unichr(920), 'D': 'E'}, "dimensions": {'A': 'B', 'B': six.unichr(920), 'D': 'E'},
"timestamp": 1405630174123, "timestamp": 1405630174123,
"value": 5} "value": 5}
metric_validator.validate(metric) metric_validator.validate(metric)
def test_valid_metric_unicode_metric_name(self): def test_valid_metric_unicode_metric_name(self):
metric = {"name": unichr(6021), metric = {"name": six.unichr(6021),
"dimensions": {"key1": "value1", "dimensions": {"key1": "value1",
"key2": "value2"}, "key2": "value2"},
"timestamp": 1405630174123, "timestamp": 1405630174123,
@ -288,7 +289,7 @@ class TestMetricValidation(unittest.TestCase):
def test_invalid_too_many_value_meta(self): def test_invalid_too_many_value_meta(self):
value_meta = {} value_meta = {}
for i in range(0, 17): for i in six.moves.range(0, 17):
value_meta['key{}'.format(i)] = 'value{}'.format(i) value_meta['key{}'.format(i)] = 'value{}'.format(i)
metric = {"name": "test_metric_name", metric = {"name": "test_metric_name",
"dimensions": {"key1": "value1", "dimensions": {"key1": "value1",
@ -315,7 +316,7 @@ class TestMetricValidation(unittest.TestCase):
def test_invalid_too_long_value_meta_key(self): def test_invalid_too_long_value_meta_key(self):
key = "K" key = "K"
for i in range(0, metric_validator.VALUE_META_NAME_MAX_LENGTH): for i in six.moves.range(0, metric_validator.VALUE_META_NAME_MAX_LENGTH):
key = "{}{}".format(key, "1") key = "{}{}".format(key, "1")
value_meta = {key: 'BBB'} value_meta = {key: 'BBB'}
metric = {"name": "test_metric_name", metric = {"name": "test_metric_name",
@ -332,10 +333,10 @@ class TestMetricValidation(unittest.TestCase):
def test_invalid_too_large_value_meta(self): def test_invalid_too_large_value_meta(self):
value_meta_value = "" value_meta_value = ""
num_value_meta = 10 num_value_meta = 10
for i in range(0, metric_validator.VALUE_META_VALUE_MAX_LENGTH / num_value_meta): for i in six.moves.range(0, int(metric_validator.VALUE_META_VALUE_MAX_LENGTH / num_value_meta)):
value_meta_value = '{}{}'.format(value_meta_value, '1') value_meta_value = '{}{}'.format(value_meta_value, '1')
value_meta = {} value_meta = {}
for i in range(0, num_value_meta): for i in six.moves.range(0, num_value_meta):
value_meta['key{}'.format(i)] = value_meta_value value_meta['key{}'.format(i)] = value_meta_value
metric = {"name": "test_metric_name", metric = {"name": "test_metric_name",
"dimensions": {"key1": "value1", "dimensions": {"key1": "value1",
@ -374,7 +375,7 @@ class TestMetricValidation(unittest.TestCase):
"timestamp": 1405630174123, "timestamp": 1405630174123,
"value": 2.0} "value": 2.0}
] ]
for i in range(len(metrics)): for i in six.moves.range(len(metrics)):
metric_validator.validate_name(metrics[i]['name']) metric_validator.validate_name(metrics[i]['name'])
metric_validator.validate_value(metrics[i]['value']) metric_validator.validate_value(metrics[i]['value'])
metric_validator.validate_timestamp(metrics[i]['timestamp']) metric_validator.validate_timestamp(metrics[i]['timestamp'])

View File

@ -15,6 +15,8 @@
import math import math
import re import re
import six
import ujson import ujson
# This is used to ensure that metrics with a timestamp older than # This is used to ensure that metrics with a timestamp older than
@ -32,6 +34,13 @@ INVALID_CHARS = "<>={}(),\"\\\\;&"
RESTRICTED_DIMENSION_CHARS = re.compile('[' + INVALID_CHARS + ']') RESTRICTED_DIMENSION_CHARS = re.compile('[' + INVALID_CHARS + ']')
RESTRICTED_NAME_CHARS = re.compile('[' + INVALID_CHARS + ' ' + ']') RESTRICTED_NAME_CHARS = re.compile('[' + INVALID_CHARS + ' ' + ']')
NUMERIC_VALUES = [int, float]
if six.PY2:
# according to PEP537 long was renamed to int in PY3
# need to add long, as possible value, for PY2
NUMERIC_VALUES += [long]
NUMERIC_VALUES = tuple(NUMERIC_VALUES) # convert to tuple for instance call
class InvalidMetricName(Exception): class InvalidMetricName(Exception):
pass pass
@ -82,7 +91,7 @@ def validate_value_meta(value_meta):
msg = "Too many valueMeta entries {0}, limit is {1}: valueMeta {2}".\ msg = "Too many valueMeta entries {0}, limit is {1}: valueMeta {2}".\
format(len(value_meta), VALUE_META_MAX_NUMBER, value_meta) format(len(value_meta), VALUE_META_MAX_NUMBER, value_meta)
raise InvalidValueMeta(msg) raise InvalidValueMeta(msg)
for key, value in value_meta.iteritems(): for key, value in six.iteritems(value_meta):
if not key: if not key:
raise InvalidValueMeta("valueMeta name cannot be empty: key={}, " raise InvalidValueMeta("valueMeta name cannot be empty: key={}, "
"value={}".format(key, value)) "value={}".format(key, value))
@ -103,7 +112,7 @@ def validate_value_meta(value_meta):
def validate_dimension_key(k): def validate_dimension_key(k):
if not isinstance(k, (str, unicode)): if not isinstance(k, (str, six.text_type)):
msg = "invalid dimension key type: " \ msg = "invalid dimension key type: " \
"{0} is not a string type".format(k) "{0} is not a string type".format(k)
raise InvalidDimensionKey(msg) raise InvalidDimensionKey(msg)
@ -118,7 +127,7 @@ def validate_dimension_key(k):
def validate_dimension_value(k, v): def validate_dimension_value(k, v):
if not isinstance(v, (str, unicode)): if not isinstance(v, (str, six.text_type)):
msg = "invalid dimension value type: {0} must be a " \ msg = "invalid dimension value type: {0} must be a " \
"string (from key {1})".format(v, k) "string (from key {1})".format(v, k)
raise InvalidDimensionValue(msg) raise InvalidDimensionValue(msg)
@ -132,13 +141,13 @@ def validate_dimension_value(k, v):
def validate_dimensions(dimensions): def validate_dimensions(dimensions):
for k, v in dimensions.iteritems(): for k, v in six.iteritems(dimensions):
validate_dimension_key(k) validate_dimension_key(k)
validate_dimension_value(k, v) validate_dimension_value(k, v)
def validate_name(name): def validate_name(name):
if not isinstance(name, (str, unicode)): if not isinstance(name, (str, six.text_type)):
msg = "invalid metric name type: {0} is not a string type ".format( msg = "invalid metric name type: {0} is not a string type ".format(
name) name)
raise InvalidMetricName(msg) raise InvalidMetricName(msg)
@ -151,7 +160,7 @@ def validate_name(name):
def validate_value(value): def validate_value(value):
if not isinstance(value, (int, long, float)): if not isinstance(value, NUMERIC_VALUES):
msg = "invalid value type: {0} is not a number type for metric".\ msg = "invalid value type: {0} is not a number type for metric".\
format(value) format(value)
raise InvalidValue(msg) raise InvalidValue(msg)
@ -161,7 +170,7 @@ def validate_value(value):
def validate_timestamp(timestamp): def validate_timestamp(timestamp):
if not isinstance(timestamp, (int, long, float)): if not isinstance(timestamp, NUMERIC_VALUES):
msg = "invalid timestamp type: {0} is not a number type for " \ msg = "invalid timestamp type: {0} is not a number type for " \
"metric".format(timestamp) "metric".format(timestamp)
raise InvalidTimeStamp(msg) raise InvalidTimeStamp(msg)

View File

@ -11,6 +11,10 @@ classifier =
Programming Language :: Python Programming Language :: Python
Programming Language :: Python :: 2.7 Programming Language :: Python :: 2.7
[global]
setup-hooks =
pbr.hooks.setup_hook
[files] [files]
packages = packages =
monasca_common monasca_common

9
test-blacklist-py3.txt Normal file
View File

@ -0,0 +1,9 @@
#################################################
# note(trebskit) Following tests fails under PY3
# reason for exclusion is written above test name
#################################################
# TypeError: catching classes that do not inherit from BaseException is not allowed
# not possible under PY3
monasca_common.tests.test_kafka.TestKafkaConsumer.test_kafka_consumer_process_messages

View File

@ -10,8 +10,8 @@ fixtures>=3.0.0 # Apache-2.0/BSD
httplib2>=0.7.5 # MIT httplib2>=0.7.5 # MIT
mock>=2.0 # BSD mock>=2.0 # BSD
mox>=0.5.3 # Apache-2.0 mox>=0.5.3 # Apache-2.0
nose # LGPL
oslotest>=1.10.0 # Apache-2.0 oslotest>=1.10.0 # Apache-2.0
os-testr>=0.8.0 # Apache-2.0
python-subunit>=0.0.18 # Apache-2.0/BSD python-subunit>=0.0.18 # Apache-2.0/BSD
testrepository>=0.0.18 # Apache-2.0/BSD testrepository>=0.0.18 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD

68
tox.ini
View File

@ -1,40 +1,72 @@
[tox] [tox]
minversion = 1.6 envlist = py{27,35},pep8,cover
minversion = 2.5
skipsdist = True skipsdist = True
envlist = py27,pep8
[testenv] [testenv]
usedevelop = True
setenv = VIRTUAL_ENV={envdir} setenv = VIRTUAL_ENV={envdir}
OS_TEST_PATH=monasca_common/tests
CLIENT_NAME=monasca-common
passenv = http_proxy passenv = http_proxy
HTTP_PROXY HTTP_PROXY
https_proxy https_proxy
HTTPS_PROXY HTTPS_PROXY
no_proxy no_proxy
NO_PROXY NO_PROXY
usedevelop = True whitelist_externals = bash
install_command = find
{toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} rm
install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
deps = -r{toxinidir}/requirements.txt deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
whitelist_externals = find
commands = commands =
find . -type f -name "*.pyc" -delete find {toxinidir} -type f -name '*.pyc' -delete
nosetests --with-coverage --cover-package=monasca_common/. --cover-erase
[testenv:py27]
basepython = python2.7
commands =
{[testenv]commands}
ostestr {posargs}
[testenv:py35]
basepython = python3.5
setenv =
{[testenv]setenv}
BLACKLIST_FILE={toxinidir}/test-blacklist-py3.txt
commands =
{[testenv]commands}
ostestr --blacklist-file {env:BLACKLIST_FILE} {posargs}
[testenv:cover]
basepython = python2.7
commands =
{[testenv]commands}
coverage erase
python setup.py test --coverage --testr-args='{posargs}' --coverage-package-name=monasca_common
coverage report
[testenv:debug]
commands =
{[testenv]commands}
oslo_debug_helper -t {env:OS_TEST_PATH} {posargs}
[testenv:bandit]
# B101(assert_ussed) - Validation uses asserts because of performance reasons
# monasca_common/kafka_lib is a clone of kafka-python and will be deleted in the future
commands = bandit -r monasca_common -n5 -s B101 -x monasca_common/tests -x monasca_common/kafka_lib
[testenv:flake8]
commands = flake8 monasca_common
[testenv:pep8] [testenv:pep8]
deps =
{[testenv]deps}
commands = commands =
{[testenv:flake8]commands} {[testenv:flake8]commands}
{[bandit]commands} {[testenv:bandit]commands}
[testenv:venv] [testenv:venv]
commands = {posargs} commands = {posargs}
[testenv:flake8]
commands =
flake8 monasca_common
[flake8] [flake8]
max-complexity = 50 max-complexity = 50
max-line-length = 120 max-line-length = 120
@ -45,9 +77,3 @@ show-source = True
# All of the below ignores are caused by the forked kafka-python library # All of the below ignores are caused by the forked kafka-python library
# so when monasca migrates to pykafka, the below line can be removed. # so when monasca migrates to pykafka, the below line can be removed.
ignore = E121,E126,E127,E128,E131,E221,E226,E241,E251,E261,E302,E303,E501,E701,F401,H101,H102,H301,H304,H306,H404,H405 ignore = E121,E126,E127,E128,E131,E221,E226,E241,E251,E261,E302,E303,E501,E701,F401,H101,H102,H301,H304,H306,H404,H405
[bandit]
commands =
# B101(assert_ussed) - Validation uses asserts because of performance reasons
# monasca_common/kafka_lib is a clone of kafka-python and will be deleted in the future
bandit -r monasca_common -n5 -s B101 -x monasca_common/tests -x monasca_common/kafka_lib