Skip to content

Commit

Permalink
Fix issue #75; Fix task tests (#80)
Browse files Browse the repository at this point in the history
  • Loading branch information
rsnyman authored Oct 27, 2020
1 parent 3e8388f commit cee9be2
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 31 deletions.
11 changes: 9 additions & 2 deletions backend/ibutsu_server/controllers/import_controller.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import connexion
from ibutsu_server.db.base import session
from ibutsu_server.db.models import Import
from ibutsu_server.db.models import ImportFile
from ibutsu_server.tasks.importers import run_archive_import
from ibutsu_server.tasks.importers import run_junit_import
from ibutsu_server.util.projects import get_project_id


def get_import(id_):
Expand All @@ -17,7 +19,7 @@ def get_import(id_):
return import_.to_dict()


def add_import(import_file=None, *args, **kwargs):
def add_import(import_file=None, project=None, *args, **kwargs):
"""Imports a JUnit XML file and creates a test run and results from it.
:param import_file: file to upload
Expand All @@ -27,8 +29,13 @@ def add_import(import_file=None, *args, **kwargs):
"""
if not import_file:
return "Bad request, no file uploaded", 400
data = {}
if connexion.request.form.get("project"):
project = connexion.request.form["project"]
if project:
data["project_id"] = get_project_id(project)
new_import = Import.from_dict(
**{"status": "pending", "filename": import_file.filename, "format": "", "data": {}}
**{"status": "pending", "filename": import_file.filename, "format": "", "data": data}
)
session.add(new_import)
session.commit()
Expand Down
3 changes: 3 additions & 0 deletions backend/ibutsu_server/openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,9 @@ paths:
description: The file to import
format: binary
type: string
project:
description: The project associated with this import
type: string
required:
- importFile
type: object
Expand Down
16 changes: 12 additions & 4 deletions backend/ibutsu_server/tasks/importers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from lxml import objectify


def _create_result(tar, run_id, result, artifacts):
def _create_result(tar, run_id, result, artifacts, project_id=None):
"""Create a result with artifacts, used in the archive importer"""
old_id = None
result_id = convert_objectid_to_uuid(result.get("id"))
Expand All @@ -33,6 +33,8 @@ def _create_result(tar, run_id, result, artifacts):
if "id" in result:
result.pop("id")
result["run_id"] = run_id
if project_id:
result["project_id"] = project_id
result_record = Result.from_dict(**result)
session.add(result_record)
session.commit()
Expand Down Expand Up @@ -85,14 +87,16 @@ def run_junit_import(import_):
"tests": testsuite.get("tests"),
},
}
if import_record.data.get("project_id"):
run_dict["project_id"] = import_record.data["project_id"]
# Insert the run, and then update the import with the run id
run = Run.from_dict(**run_dict)
session.add(run)
session.commit()
run_dict = run.to_dict()
import_record.data["run_id"].append(run.id)
# Import the contents of the XML file
for testcase in testsuite.testcase:
for testcase in testsuite.iterchildren(tag="testcase"):
test_name = testcase.get("name").split(".")[-1]
if testcase.get("classname"):
test_name = testcase.get("classname").split(".")[-1] + "." + test_name
Expand All @@ -109,6 +113,8 @@ def run_junit_import(import_):
"params": {},
"source": testsuite.get("name"),
}
if import_record.data.get("project_id"):
result_dict["project_id"] = import_record.data["project_id"]
skip_reason, traceback = None, None
if testcase.find("failure"):
result_dict["result"] = "failed"
Expand Down Expand Up @@ -231,7 +237,9 @@ def run_archive_import(import_):
elif not run_dict.get("created") and not run_dict.get("start_time"):
run_dict["created"] = start_time
run_dict["start_time"] = start_time
if run_dict.get("metadata", {}).get("project"):
if import_record.data.get("project_id"):
run_dict["project_id"] = import_record.data["project_id"]
elif run_dict.get("metadata", {}).get("project"):
run_dict["project_id"] = get_project_id(run_dict["metadata"]["project"])
# If this run has a valid ObjectId, check if this run exists
if is_uuid(run_dict.get("id")):
Expand All @@ -246,7 +254,7 @@ def run_archive_import(import_):
# Now loop through all the results, and create or update them
for result in results:
artifacts = result_artifacts.get(result["id"], [])
_create_result(tar, run.id, result, artifacts)
_create_result(tar, run.id, result, artifacts, import_record.data.get("project_id"))
# Update the import record
_update_import_status(import_record, "done")
if run:
Expand Down
28 changes: 26 additions & 2 deletions backend/ibutsu_server/test/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
from copy import copy
from unittest.mock import MagicMock
from inspect import isfunction

import ibutsu_server.tasks
from flask_testing import TestCase
Expand All @@ -9,6 +9,27 @@
from ibutsu_server.util import merge_dicts


def mock_task(*args, **kwargs):
if args and isfunction(args[0]):
func = args[0]

def wrap(*args, **kwargs):
return func(*args, **kwargs)

wrap._orig_func = func
return wrap
else:

def decorate(func):
def _wrapped(*args, **kwargs):
return func(*args, **kwargs)

_wrapped._orig_func = func
return _wrapped

return decorate


class BaseTestCase(TestCase):
def create_app(self):
logging.getLogger("connexion.operation").setLevel("ERROR")
Expand All @@ -19,6 +40,9 @@ def create_app(self):
}
app = get_app(**extra_config)
create_celery_app(app.app)

if ibutsu_server.tasks.task is None:
ibutsu_server.tasks.task = mock_task
return app.app

def assert_201(self, response, message=None):
Expand Down Expand Up @@ -142,4 +166,4 @@ class MockRun(MockModel):


# Mock out the task decorator
ibutsu_server.tasks.task = MagicMock()
ibutsu_server.tasks.task = mock_task
9 changes: 9 additions & 0 deletions backend/ibutsu_server/test/res/empty-testsuite.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="Tests" time="15.943" tests="1" failures="0">
<testsuite name="Root Suite" timestamp="2020-10-05T20:41:16" tests="0" file="root-suite.spec.js" failures="0" time="0">
</testsuite>
<testsuite name="Visual Testing" timestamp="2020-10-05T20:41:16" tests="1" failures="0" time="15.943">
<testcase name="Test navigation" time="15.943" classname="navigation">
</testcase>
</testsuite>
</testsuites>
60 changes: 37 additions & 23 deletions backend/ibutsu_server/test/test_tasks.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,63 @@
import time
import uuid
from datetime import datetime
from unittest.mock import MagicMock
from unittest.mock import patch

import pytest
from ibutsu_server.test import BaseTestCase

MOCK_RUN_ID = str(uuid.uuid4())
MOCK_RUN = {"id": MOCK_RUN_ID}
MOCK_RUN = MagicMock(**{"id": MOCK_RUN_ID, "data": {}})
MOCK_PROJECT = str(uuid.uuid4())
MOCK_TIME = time.time()
MOCK_RESULTS = [
{
"result": "passed",
MagicMock(
**{
"result": "passed",
"duration": 1.532734345,
"data": {"component": "login", "env": "qa", "project": MOCK_PROJECT},
"starttime": MOCK_TIME,
}
)
]
UPDATED_RUN = MagicMock(
**{
"id": MOCK_RUN_ID,
"duration": 1.532734345,
"metadata": {"component": "login", "env": "qa", "project": MOCK_PROJECT},
"starttime": MOCK_TIME,
"summary": {
"errors": 0,
"failures": 0,
"skips": 0,
"xfailures": 0,
"xpasses": 0,
"tests": 1,
},
"data": {"component": "login", "env": "qa", "project": MOCK_PROJECT},
"start_time": MOCK_TIME,
"created": datetime.fromtimestamp(MOCK_TIME).isoformat(),
}
]
UPDATED_RUN = {
"id": MOCK_RUN_ID,
"duration": 1.532734345,
"summary": {"errors": 0, "failures": 0, "skips": 0, "xfailures": 0, "xpasses": 0, "tests": 1},
"metadata": {"component": "login", "env": "qa", "project": MOCK_PROJECT},
"start_time": MOCK_TIME,
"created": datetime.fromtimestamp(MOCK_TIME).isoformat(),
}
)


@pytest.mark.skip("Currently breaking collection")
class TestRunTasks(BaseTestCase):
def test_update_run(self, mocker):
@patch("ibutsu_server.tasks.runs.Result")
@patch("ibutsu_server.tasks.runs.Run")
@patch("ibutsu_server.tasks.runs.session")
@patch("ibutsu_server.tasks.runs.lock")
def test_update_run(self, mocked_lock, mocked_session, mocked_run, mocked_result):
"""Test updating the run"""
from ibutsu_server.tasks.runs import update_run

mocker.patch("ibutsu_server.tasks.runs.lock")
mocked_session = mocker.patch("ibutsu_server.tasks.runs.session")
mocked_run = mocker.patch("ibutsu_server.tasks.runs.Run")
mocked_lock.return_value.__enter__.return_value = None
mocked_run.query.get.return_value = MOCK_RUN
mocked_result = mocker.patch("ibutsu_server.tasks.runs.Result")
mocked_result.query.return_value.filter.return_value.all.return_value = MOCK_RESULTS

update_run = update_run._orig_func
update_run(MOCK_RUN_ID)

mocked_lock.assert_called_once()
mocked_run.query.get.assert_called_once_with(MOCK_RUN_ID)
mocked_result.query.return_value.filter.assert_called_once()
mocked_result.query.return_value.filter.return_value.all.assert_called_once()
mocked_result.query.filter.assert_called_once()
mocked_result.query.filter.return_value.order_by.return_value.all.assert_called_once()
mocked_session.add.assert_called_once()
mocked_session.commit.assert_called_once()

0 comments on commit cee9be2

Please sign in to comment.