Enable python 3 testing support

In an effort to being really supporting using subunit2sql in a python3
environment this patch fixes all the issues with python3
incompatibility that show up when running tests. However, because the
test coverage is limited for certain parts there are still probably
pieces which don't work with python 3.

Change-Id: I160d1675069836fa514547c31866b22bcaf29dcb
This commit is contained in:
Matthew Treinish 2015-10-05 00:38:22 -04:00
parent be5a896e1b
commit fa82de131c
No known key found for this signature in database
GPG Key ID: FD12A0F214C9E177
10 changed files with 30 additions and 27 deletions

View File

@ -59,7 +59,7 @@ def generate_series():
plt.figure() plt.figure()
plt.barh(range(len(perc_data)), perc_data.values(), align='center') plt.barh(range(len(perc_data)), perc_data.values(), align='center')
locs, labels = plt.yticks(range(len(perc_data)), perc_data.keys()) locs, labels = plt.yticks(range(len(perc_data)), list(perc_data.keys()))
plt.xlabel('Failure Percentage') plt.xlabel('Failure Percentage')
plt.tight_layout() plt.tight_layout()
plt.savefig(CONF.output, dpi=900) plt.savefig(CONF.output, dpi=900)

View File

@ -18,6 +18,7 @@ import datetime
from oslo_config import cfg from oslo_config import cfg
from oslo_db.sqlalchemy import session as db_session from oslo_db.sqlalchemy import session as db_session
from oslo_db.sqlalchemy import utils as db_utils from oslo_db.sqlalchemy import utils as db_utils
import six
import sqlalchemy import sqlalchemy
from sqlalchemy.engine.url import make_url from sqlalchemy.engine.url import make_url
@ -45,7 +46,7 @@ def _create_facade_lazily():
if facade is None: if facade is None:
facade = db_session.EngineFacade( facade = db_session.EngineFacade(
CONF.database.connection, CONF.database.connection,
**dict(CONF.database.iteritems())) **dict(six.iteritems(CONF.database)))
_facades[db_backend] = facade _facades[db_backend] = facade
return facade return facade
@ -820,7 +821,7 @@ def get_recent_successful_runs(num_runs=10, session=None):
session = session or get_session() session = session or get_session()
results = db_utils.model_query(models.Run, session).order_by( results = db_utils.model_query(models.Run, session).order_by(
models.Run.run_at.desc()).filter_by(fails=0).limit(num_runs).all() models.Run.run_at.desc()).filter_by(fails=0).limit(num_runs).all()
return map(lambda x: x.id, results) return list(map(lambda x: x.id, results))
def get_recent_failed_runs(num_runs=10, session=None): def get_recent_failed_runs(num_runs=10, session=None):
@ -836,7 +837,7 @@ def get_recent_failed_runs(num_runs=10, session=None):
results = db_utils.model_query(models.Run, session).order_by( results = db_utils.model_query(models.Run, session).order_by(
models.Run.run_at.desc()).filter( models.Run.run_at.desc()).filter(
models.Run.fails > 0).limit(num_runs).all() models.Run.fails > 0).limit(num_runs).all()
return map(lambda x: x.id, results) return list(map(lambda x: x.id, results))
def delete_old_runs(expire_age=186, session=None): def delete_old_runs(expire_age=186, session=None):
@ -1062,7 +1063,7 @@ def get_all_runs_time_series_by_key(key, start_date=None,
'skip': run[3], 'skip': run[3],
}]} }]}
else: else:
if run[4] not in runs[run[0]].keys(): if run[4] not in list(runs[run[0]].keys()):
runs[run[0]][run[4]] = [{ runs[run[0]][run[4]] = [{
'pass': run[1], 'pass': run[1],
'fail': run[2], 'fail': run[2],

View File

@ -32,7 +32,7 @@ class SubunitBase(models.ModelBase):
super(SubunitBase, self).save(session or db_api.get_session()) super(SubunitBase, self).save(session or db_api.get_session())
def keys(self): def keys(self):
return self.__dict__.keys() return list(self.__dict__.keys())
def values(self): def values(self):
return self.__dict__.values() return self.__dict__.values()

View File

@ -14,6 +14,8 @@
import datetime import datetime
import six
from six import moves
import testscenarios import testscenarios
from subunit2sql.db import api from subunit2sql.db import api
@ -213,7 +215,7 @@ class TestDatabaseAPI(base.TestCase):
# 10 with 10 failures # 10 with 10 failures
# 7 in 2010/2011 each, 6 in 2012 # 7 in 2010/2011 each, 6 in 2012
# 10 in projecta/projectb each # 10 in projecta/projectb each
for i in range(20): for i in moves.range(20):
if i % 2 == 1: if i % 2 == 1:
fails = 10 fails = 10
else: else:
@ -250,7 +252,7 @@ class TestDatabaseAPI(base.TestCase):
def test_get_time_series_runs_by_key_value(self): def test_get_time_series_runs_by_key_value(self):
runs = [] runs = []
run_at = datetime.datetime.utcnow() run_at = datetime.datetime.utcnow()
for run_num in xrange(15): for run_num in moves.range(15):
run = api.create_run(run_num, run_num + 1, run_num + 2, 3, run = api.create_run(run_num, run_num + 1, run_num + 2, 3,
run_at=run_at) run_at=run_at)
runs.append(run) runs.append(run)
@ -262,14 +264,14 @@ class TestDatabaseAPI(base.TestCase):
runs_time_series = api.get_time_series_runs_by_key_value('test_key', runs_time_series = api.get_time_series_runs_by_key_value('test_key',
'fun') 'fun')
self.assertEqual(1, len(runs_time_series)) self.assertEqual(1, len(runs_time_series))
timestamp = runs_time_series.keys()[0] timestamp = list(runs_time_series.keys())[0]
self.assertEqual(3, len(runs_time_series[timestamp])) self.assertEqual(3, len(runs_time_series[timestamp]))
for run_num in xrange(3): for run_num in moves.range(3):
run_dict = { run_dict = {
'skip': long(run_num), 'skip': run_num,
'fail': long(run_num + 1), 'fail': run_num + 1,
'pass': long(run_num + 2), 'pass': run_num + 2,
'id': unicode(runs[run_num].id), 'id': six.text_type(runs[run_num].id),
'run_time': 3.0, 'run_time': 3.0,
'metadata': { 'metadata': {
u'test_key': u'fun', u'test_key': u'fun',
@ -277,12 +279,12 @@ class TestDatabaseAPI(base.TestCase):
} }
} }
self.assertIn(run_dict, runs_time_series[timestamp]) self.assertIn(run_dict, runs_time_series[timestamp])
for run_num in range(3, 14): for run_num in moves.range(3, 14):
missing_run_dict = { missing_run_dict = {
'skip': long(run_num), 'skip': run_num,
'fail': long(run_num + 1), 'fail': run_num + 1,
'pass': long(run_num + 2), 'pass': run_num + 2,
'id': unicode(runs[run_num].id), 'id': six.text_type(runs[run_num].id),
'run_time': 3.0, 'run_time': 3.0,
'metadata': { 'metadata': {
u'test_key': u'fun', u'test_key': u'fun',

View File

@ -39,7 +39,7 @@ def get_connect_string(backend,
these then we'll run the tests, otherwise they are skipped these then we'll run the tests, otherwise they are skipped
""" """
if backend == "mysql": if backend == "mysql":
backend = "mysql+mysqldb" backend = "mysql+pymysql"
elif backend == "postgres": elif backend == "postgres":
backend = "postgresql+psycopg2" backend = "postgresql+psycopg2"

View File

@ -14,13 +14,13 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import ConfigParser
import datetime import datetime
import os import os
from alembic import config from alembic import config
from alembic import script from alembic import script
from six.moves import configparser as ConfigParser
import sqlalchemy import sqlalchemy
from subunit2sql import exceptions as exc from subunit2sql import exceptions as exc
@ -273,7 +273,7 @@ class TestWalkMigrations(base.TestCase):
runs.insert().values(time_data).execute() runs.insert().values(time_data).execute()
runs = get_table(engine, 'runs') runs = get_table(engine, 'runs')
result = runs.select().execute() result = runs.select().execute()
run_at = map(lambda x: (x['id'], x['run_at']), result) run_at = list(map(lambda x: (x['id'], x['run_at']), result))
for run in data: for run in data:
self.assertIn((run['id'], None), run_at) self.assertIn((run['id'], None), run_at)
self.assertIn((time_data['id'], now), run_at) self.assertIn((time_data['id'], now), run_at)
@ -320,7 +320,7 @@ class TestWalkMigrations(base.TestCase):
# Query the DB for the tests from the sample dataset above # Query the DB for the tests from the sample dataset above
where = ' OR '.join(["tests.id='%s'" % x for x in test_ids]) where = ' OR '.join(["tests.id='%s'" % x for x in test_ids])
result = tests.select(where).execute() result = tests.select(where).execute()
run_time_pairs = map(lambda x: (x['id'], x['run_time']), result) run_time_pairs = list(map(lambda x: (x['id'], x['run_time']), result))
# Ensure the test with one failure is None # Ensure the test with one failure is None
self.assertIn(('fake_null_test_id_fails', None), run_time_pairs) self.assertIn(('fake_null_test_id_fails', None), run_time_pairs)
# Ensure the test with 2 success each taking 4 sec lists the proper # Ensure the test with 2 success each taking 4 sec lists the proper

View File

@ -15,13 +15,13 @@
import os import os
import shutil import shutil
import subprocess import subprocess
import urlparse
import fixtures as fix import fixtures as fix
from oslo_concurrency.fixture import lockutils as lock_fixture from oslo_concurrency.fixture import lockutils as lock_fixture
from oslo_concurrency import lockutils from oslo_concurrency import lockutils
from oslo_config import fixture as config_fixture from oslo_config import fixture as config_fixture
from oslo_db import options from oslo_db import options
from six.moves.urllib import parse as urlparse
from subunit2sql.db import api as session from subunit2sql.db import api as session
from subunit2sql.migrations import cli from subunit2sql.migrations import cli

View File

@ -110,7 +110,7 @@ class TestReadSubunit(base.TestCase):
# assert that the dict root key is the test name - the fake_id stripped # assert that the dict root key is the test name - the fake_id stripped
# of the tags # of the tags
fake_test_name = fake_id[:fake_id.find('[')] fake_test_name = fake_id[:fake_id.find('[')]
self.assertEqual(parsed_results.keys(), [fake_test_name]) self.assertEqual(list(parsed_results.keys()), [fake_test_name])
self.assertEqual(parsed_results[fake_test_name]['status'], self.assertEqual(parsed_results[fake_test_name]['status'],
fake_status) fake_status)

View File

@ -8,6 +8,6 @@ testscenarios>=0.4
testrepository>=0.0.18 testrepository>=0.0.18
testtools>=0.9.34 testtools>=0.9.34
oslosphinx oslosphinx
MySQL-python PyMySql
psycopg2 psycopg2
os-testr os-testr

View File

@ -1,6 +1,6 @@
[tox] [tox]
minversion = 1.6 minversion = 1.6
envlist = py27,py34,pep8 envlist = py34,py27,pep8
skipsdist = True skipsdist = True
[testenv] [testenv]