Skip to content

Commit 2ab3978

Browse files
committed
test: use responses in test/test_create.py
This allows us to get more coverage out of these tests.
1 parent 37d045e commit 2ab3978

File tree

2 files changed

+68
-23
lines changed

2 files changed

+68
-23
lines changed

test/test_create.py

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,69 @@
22
# License, v. 2.0. If a copy of the MPL was not distributed with this
33
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
44

5-
5+
import json
6+
import re
67
import unittest
78
from unittest import mock
89

10+
import responses
11+
from taskcluster.exceptions import TaskclusterRestFailure
12+
913
from taskgraph import create
1014
from taskgraph.config import GraphConfig
1115
from taskgraph.graph import Graph
1216
from taskgraph.task import Task
1317
from taskgraph.taskgraph import TaskGraph
18+
from taskgraph.util import taskcluster as tc_util
1419

1520
GRAPH_CONFIG = GraphConfig({"trust-domain": "domain"}, "/var/empty")
1621

1722

18-
class TestCreate(unittest.TestCase):
19-
def setUp(self):
20-
self.created_tasks = {}
21-
self.old_create_task = create.create_task
22-
create.create_task = self.fake_create_task
23+
def mock_taskcluster_api(
24+
created_tasks=None, error_status=None, error_message=None, error_task_ids=None
25+
):
26+
"""Mock the Taskcluster Queue API for create task calls."""
27+
28+
def request_callback(request):
29+
task_id = request.url.split("/")[-1]
30+
31+
# Check if this task should error
32+
if error_status is not None:
33+
if error_task_ids is None or task_id in error_task_ids:
34+
# Support per-task error messages
35+
if isinstance(error_message, dict):
36+
message = error_message.get(task_id, "error")
37+
else:
38+
message = error_message or "error"
39+
return (error_status, {}, f'{{"message": "{message}"}}')
40+
41+
# Success case - capture task definition if requested
42+
if created_tasks is not None:
43+
task_def = json.loads(request.body)
44+
created_tasks[task_id] = task_def
45+
46+
return (200, {}, f'{{"status": {{"taskId": "{task_id}"}}}}')
2347

24-
def tearDown(self):
25-
create.create_task = self.old_create_task
48+
responses.add_callback(
49+
responses.PUT,
50+
re.compile(r"https://tc\.example\.com/api/queue/v1/task/.*"),
51+
callback=request_callback,
52+
content_type="application/json",
53+
)
2654

27-
def fake_create_task(self, session, task_id, label, task_def):
28-
self.created_tasks[task_id] = task_def
2955

56+
class TestCreate(unittest.TestCase):
57+
def setUp(self):
58+
# Clear cached Taskcluster clients/sessions since we're mocking the environment
59+
tc_util.get_taskcluster_client.cache_clear()
60+
tc_util.get_session.cache_clear()
61+
62+
@responses.activate
63+
@mock.patch.dict("os.environ", {"TASKCLUSTER_ROOT_URL": "https://tc.example.com"})
3064
def test_create_tasks(self):
65+
created_tasks = {}
66+
mock_taskcluster_api(created_tasks=created_tasks)
67+
3168
tasks = {
3269
"tid-a": Task(
3370
kind="test", label="a", attributes={}, task={"payload": "hello world"}
@@ -48,18 +85,24 @@ def test_create_tasks(self):
4885
decision_task_id="decisiontask",
4986
)
5087

51-
for tid, task in self.created_tasks.items():
88+
assert created_tasks
89+
for tid, task in created_tasks.items():
5290
self.assertEqual(task["payload"], "hello world")
5391
self.assertEqual(task["schedulerId"], "domain-level-4")
5492
# make sure the dependencies exist, at least
5593
for depid in task.get("dependencies", []):
5694
if depid == "decisiontask":
5795
# Don't look for decisiontask here
5896
continue
59-
self.assertIn(depid, self.created_tasks)
97+
self.assertIn(depid, created_tasks)
6098

99+
@responses.activate
100+
@mock.patch.dict("os.environ", {"TASKCLUSTER_ROOT_URL": "https://tc.example.com"})
61101
def test_create_task_without_dependencies(self):
62102
"a task with no dependencies depends on the decision task"
103+
created_tasks = {}
104+
mock_taskcluster_api(created_tasks=created_tasks)
105+
63106
tasks = {
64107
"tid-a": Task(
65108
kind="test", label="a", attributes={}, task={"payload": "hello world"}
@@ -77,12 +120,16 @@ def test_create_task_without_dependencies(self):
77120
decision_task_id="decisiontask",
78121
)
79122

80-
for tid, task in self.created_tasks.items():
123+
assert created_tasks
124+
for tid, task in created_tasks.items():
81125
self.assertEqual(task.get("dependencies"), ["decisiontask"])
82126

83-
@mock.patch("taskgraph.create.create_task")
84-
def test_create_tasks_fails_if_create_fails(self, create_task):
85-
"creat_tasks fails if a single create_task call fails"
127+
@responses.activate
128+
@mock.patch.dict("os.environ", {"TASKCLUSTER_ROOT_URL": "https://tc.example.com"})
129+
def test_create_tasks_fails_if_create_fails(self):
130+
"create_tasks fails if a single create_task call fails"
131+
mock_taskcluster_api(error_status=403, error_message="oh no!")
132+
86133
tasks = {
87134
"tid-a": Task(
88135
kind="test", label="a", attributes={}, task={"payload": "hello world"}
@@ -92,13 +139,7 @@ def test_create_tasks_fails_if_create_fails(self, create_task):
92139
graph = Graph(nodes={"tid-a"}, edges=set())
93140
taskgraph = TaskGraph(tasks, graph)
94141

95-
def fail(*args):
96-
print("UHOH")
97-
raise RuntimeError("oh no!")
98-
99-
create_task.side_effect = fail
100-
101-
with self.assertRaises(RuntimeError):
142+
with self.assertRaises(TaskclusterRestFailure):
102143
create.create_tasks(
103144
GRAPH_CONFIG,
104145
taskgraph,

test/test_docker.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from taskgraph import docker
99
from taskgraph.config import GraphConfig
1010
from taskgraph.transforms.docker_image import IMAGE_BUILDER_IMAGE
11+
from taskgraph.util import taskcluster as tc_util
1112
from taskgraph.util.vcs import get_repository
1213

1314
from .conftest import nowin
@@ -22,6 +23,9 @@ def root_url():
2223
def mock_environ(monkeypatch, root_url):
2324
# Ensure user specified environment variables don't interfere with URLs.
2425
monkeypatch.setattr(os, "environ", {"TASKCLUSTER_ROOT_URL": root_url})
26+
# Clear cached Taskcluster clients/sessions since we're mocking the environment
27+
tc_util.get_taskcluster_client.cache_clear()
28+
tc_util.get_session.cache_clear()
2529

2630

2731
@pytest.fixture(autouse=True, scope="module")

0 commit comments

Comments
 (0)