From cfd912c330c40d120125500aa52698095aa512f4 Mon Sep 17 00:00:00 2001 From: Ralph Bean Date: Apr 04 2018 13:00:16 +0000 Subject: [PATCH 1/2] Make the list of allowed outcomes configurable. --- diff --git a/resultsdb/alembic/versions/cd581d0e83df_change_outcome_from_enum_to_string.py b/resultsdb/alembic/versions/cd581d0e83df_change_outcome_from_enum_to_string.py new file mode 100644 index 0000000..6e730f1 --- /dev/null +++ b/resultsdb/alembic/versions/cd581d0e83df_change_outcome_from_enum_to_string.py @@ -0,0 +1,30 @@ +"""Change outcome from enum to string. + +Revision ID: cd581d0e83df +Revises: 4dbe714897fe +Create Date: 2018-03-28 20:47:27.338605 + +""" + +# revision identifiers, used by Alembic. +revision = 'cd581d0e83df' +down_revision = '4dbe714897fe' +branch_labels = None +depends_on = None + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.execute( + "ALTER TABLE result " + "ALTER COLUMN outcome " + "TYPE VARCHAR(32)") + + +def downgrade(): + op.execute( + "ALTER TABLE result " + "ALTER COLUMN outcome " + "TYPE resultoutcome USING outcome::resultoutcome") diff --git a/resultsdb/config.py b/resultsdb/config.py index e4ba6b8..9402eeb 100644 --- a/resultsdb/config.py +++ b/resultsdb/config.py @@ -46,6 +46,9 @@ class Config(object): 'create_testcase': [], } + # Extend the list of allowed outcomes. + ADDITIONAL_RESULT_OUTCOMES = () + # Supported values: "oidc" AUTH_MODULE = None @@ -110,3 +113,4 @@ class TestingConfig(Config): TRAP_BAD_REQUEST_ERRORS = True FEDMENU_URL = 'https://apps.stg.fedoraproject.org/fedmenu' FEDMENU_DATA_URL = 'https://apps.stg.fedoraproject.org/js/data.js' + ADDITIONAL_RESULT_OUTCOMES = ('AMAZING',) diff --git a/resultsdb/controllers/api_v1.py b/resultsdb/controllers/api_v1.py index 1eda3f1..9eeea42 100644 --- a/resultsdb/controllers/api_v1.py +++ b/resultsdb/controllers/api_v1.py @@ -683,5 +683,6 @@ def landing_page(): "documentation": "http://docs.resultsdb.apiary.io/", "jobs": url_for('.get_jobs', _external=True), "results": url_for('.get_results', _external=True), - "testcases": url_for('.get_testcases', _external=True) + "testcases": url_for('.get_testcases', _external=True), + "outcomes": RESULT_OUTCOME, }), 300 diff --git a/resultsdb/controllers/api_v2.py b/resultsdb/controllers/api_v2.py index 983f5ed..aae7192 100644 --- a/resultsdb/controllers/api_v2.py +++ b/resultsdb/controllers/api_v2.py @@ -779,5 +779,6 @@ def landing_page(): "documentation": "http://docs.resultsdb20.apiary.io/", "groups": url_for('.get_groups', _external=True), "results": url_for('.get_results', _external=True), - "testcases": url_for('.get_testcases', _external=True) + "testcases": url_for('.get_testcases', _external=True), + "outcomes": RESULT_OUTCOME, }), 300 diff --git a/resultsdb/models/results.py b/resultsdb/models/results.py index e07e832..95017a7 100644 --- a/resultsdb/models/results.py +++ b/resultsdb/models/results.py @@ -20,14 +20,14 @@ import datetime import uuid as lib_uuid -from resultsdb import db +from resultsdb import db, app from resultsdb.serializers import DBSerialize __all__ = ['Testcase', 'Group', 'Result', 'ResultData', 'GroupsToResults', 'RESULT_OUTCOME'] - -RESULT_OUTCOME = ('PASSED', 'INFO', 'FAILED', 'NEEDS_INSPECTION') +PRESET_OUTCOMES = ('PASSED', 'INFO', 'FAILED', 'NEEDS_INSPECTION') +RESULT_OUTCOME = PRESET_OUTCOMES + app.config.get('ADDITIONAL_RESULT_OUTCOMES', []) JOB_STATUS = [] @@ -95,7 +95,7 @@ class Result(db.Model, DBSerialize): testcase_name = db.Column(db.Text, db.ForeignKey('testcase.name')) submit_time = db.Column(db.DateTime, default=datetime.datetime.utcnow) - outcome = db.Column(db.Enum(*RESULT_OUTCOME, name='resultoutcome')) + outcome = db.Column(db.String(32)) note = db.Column(db.Text) ref_url = db.Column(db.Text) diff --git a/testing/functest_api_v20.py b/testing/functest_api_v20.py index 36080b9..f3c0c60 100644 --- a/testing/functest_api_v20.py +++ b/testing/functest_api_v20.py @@ -853,3 +853,27 @@ class TestFuncApiV20(): assert plugin.history[0]['groups'] == [self.ref_group_uuid] assert plugin.history[0]['note'] == self.ref_result_note assert plugin.history[0]['testcase']['name'] == self.ref_testcase_name + + def test_create_result_custom_outcome(self): + self.test_create_group() + self.test_create_testcase() + ref_result = copy.deepcopy(self.ref_result) + ref_result['outcome'] = 'AMAZING' + + r, data = self.helper_create_result(outcome='AMAZING') + + assert r.status_code == 201 + assert data == ref_result + + ref_result = copy.deepcopy(self.ref_result) + ref_result['outcome'] = 'SILLY' + + r, data = self.helper_create_result(outcome='SILLY') + + assert r.status_code == 400 + + def test_get_outcomes_on_landing_page(self): + r = self.app.get('/api/v2.0/') + data = json.loads(r.data) + assert r.status_code == 300 + assert data['outcomes'] == ['PASSED', 'INFO', 'FAILED', 'NEEDS_INSPECTION', 'AMAZING'] From 0bbe6df94405e74d4d3779debd077ff62745826a Mon Sep 17 00:00:00 2001 From: Josef Skladanka Date: Apr 04 2018 13:00:27 +0000 Subject: [PATCH 2/2] Minor polishing of previous commit --- diff --git a/resultsdb/alembic/versions/cd581d0e83df_change_outcome_from_enum_to_string.py b/resultsdb/alembic/versions/cd581d0e83df_change_outcome_from_enum_to_string.py index 6e730f1..8c82026 100644 --- a/resultsdb/alembic/versions/cd581d0e83df_change_outcome_from_enum_to_string.py +++ b/resultsdb/alembic/versions/cd581d0e83df_change_outcome_from_enum_to_string.py @@ -17,14 +17,11 @@ import sqlalchemy as sa def upgrade(): - op.execute( - "ALTER TABLE result " - "ALTER COLUMN outcome " - "TYPE VARCHAR(32)") + op.alter_column('result', 'outcome', type_=sa.String(32)) + op.create_index('result_idx_outcome', 'result', [ + 'outcome'], unique=False, postgresql_ops={'outcome': 'text_pattern_ops'}) def downgrade(): - op.execute( - "ALTER TABLE result " - "ALTER COLUMN outcome " - "TYPE resultoutcome USING outcome::resultoutcome") + op.execute("ALTER TABLE result ALTER COLUMN outcome TYPE resultoutcome USING outcome::resultoutcome;") + op.drop_index('result_idx_outcome', table_name='result') diff --git a/resultsdb/models/results.py b/resultsdb/models/results.py index 95017a7..849160d 100644 --- a/resultsdb/models/results.py +++ b/resultsdb/models/results.py @@ -106,6 +106,9 @@ class Result(db.Model, DBSerialize): db.Index('result_fk_testcase_name', 'testcase_name', postgresql_ops={'testcase_name': 'text_pattern_ops'}), db.Index('result_submit_time', 'submit_time'), + db.Index('result_idx_outcome', 'outcome', + postgresql_ops={'outcome': 'text_pattern_ops'}, + ), ) def __init__(self, testcase, outcome, groups=None, ref_url=None, note=None): diff --git a/testing/functest_api_v20.py b/testing/functest_api_v20.py index f3c0c60..03d8f88 100644 --- a/testing/functest_api_v20.py +++ b/testing/functest_api_v20.py @@ -429,6 +429,17 @@ class TestFuncApiV20(): assert r.status_code == 201 assert data == self.ref_result + def test_create_result_custom_outcome(self): + self.test_create_group() + self.test_create_testcase() + ref_result = copy.deepcopy(self.ref_result) + ref_result['outcome'] = 'AMAZING' + + r, data = self.helper_create_result(outcome='AMAZING') + + assert r.status_code == 201 + assert data == ref_result + def test_create_result_missing_data(self): ref_data = json.dumps({'outcome': 'FAKEOUTCOME'}) r = self.app.post('/api/v2.0/results', data=ref_data, content_type='application/json') @@ -854,24 +865,6 @@ class TestFuncApiV20(): assert plugin.history[0]['note'] == self.ref_result_note assert plugin.history[0]['testcase']['name'] == self.ref_testcase_name - def test_create_result_custom_outcome(self): - self.test_create_group() - self.test_create_testcase() - ref_result = copy.deepcopy(self.ref_result) - ref_result['outcome'] = 'AMAZING' - - r, data = self.helper_create_result(outcome='AMAZING') - - assert r.status_code == 201 - assert data == ref_result - - ref_result = copy.deepcopy(self.ref_result) - ref_result['outcome'] = 'SILLY' - - r, data = self.helper_create_result(outcome='SILLY') - - assert r.status_code == 400 - def test_get_outcomes_on_landing_page(self): r = self.app.get('/api/v2.0/') data = json.loads(r.data)