def test_reply_to_error_message(datetime_mock, caplog, event_loop): settings = MockSettings({}) client = MockClient(settings) scheduler = Scheduler(settings, client, [], 'my_worker_id') with pytest.raises(SystemExit): datetime_mock.utcnow = mock.Mock(return_value=datetime(2000, 1, 1)) event_loop.run_until_complete( scheduler.on_server_message(MessageType.Error.value, { 'title': 'title', 'body': 'body', 'meta': { 'Name': 'Value', }, })) assert error_messages(caplog) == [ '\n' '\n' ' ' '================================================================================\n' '\n' ' [ERROR] [CONQUER] title\n' '\n' ' body\n' '\n' ' [Name = Value]\n' ' [Timestamp = 2000-01-01T00:00:00]\n' '\n' ' ' '================================================================================\n' '\n', ]
async def test_reply_to_done_message(): settings = MockSettings({}) client = MockClient(settings) scheduler = Scheduler(settings, client, [], 'my_worker_id') assert scheduler.more is True await scheduler.on_server_message(MessageType.Done.value, None) assert scheduler.more is False await scheduler.stop()
async def run_task(self): global suite_items, schedulers, report_items_by_worker # init client client = Client(settings) client.subscribe(self.settings) # init scheduler scheduler = Scheduler(self.settings, client, suite_items, self.name) schedulers.append(scheduler) # connect to server await client.start() # work through test items next_tests = [] report_items_by_worker[self.name] = [] while not scheduler.done: pending_at = datetime.utcnow() schedule = await scheduler.next() if schedule is None: break # happens when we are done started_at = datetime.utcnow() schedule_files = [item.file for item in schedule.items] schedule_tests = itertools.chain( *[tests_by_file[f] for f in schedule_files]) for test in schedule_tests: test.__schedule_id__ = schedule.id next_tests.append(test) logger.info('preparing schedule took %sms', str(started_at - pending_at)) while next_tests: if len(next_tests) < 2 and not scheduler.done: logger.info('requiring next schedule') break # we don't know the next test yet test = next_tests.pop(0) next_test = next_tests[0] if next_tests else None test.config.hook.pytest_runtest_protocol(item=test, nextitem=next_test) if next_test is None or test.__schedule_id__ != next_test.__schedule_id__: report = Report(test.__schedule_id__, report_items_by_worker[self.name], pending_at, started_at, datetime.utcnow()) await scheduler.report(report) report_items_by_worker[self.name] = [] # wrap things up await scheduler.stop() await client.stop()
async def test_reply_to_schedule_message(): class MockSerializer: @staticmethod def deserialize_schedule(payload): return Schedule(payload['id'], payload['items']) settings = MockSettings({}) client = MockClient(settings) scheduler = Scheduler(settings, client, [], 'my_worker_id', MockSerializer) payload = [{'id': 'ID', 'items': [['A'], ['B']]}] await scheduler.on_server_message(MessageType.Schedules.value, payload) assert await scheduler.next() == Schedule('ID', [['A'], ['B']]) await scheduler.stop()
async def test_reply_to_config_message(): class MockSerializer: @staticmethod def serialize_config(settings, worker_id): return (settings, worker_id) settings = MockSettings({}) client = MockClient(settings) scheduler = Scheduler(settings, client, [], 'my_worker_id', MockSerializer) await scheduler.on_server_message(MessageType.Config.value, None) assert client.received == [ (MessageType.Config, (settings, 'my_worker_id')), ] await scheduler.stop()
async def test_report(): class MockSerializer: @staticmethod def serialize_report(report): return report settings = MockSettings({}) client = MockClient(settings) scheduler = Scheduler(settings, client, [], 'my_worker_id', MockSerializer) report = Report('ID', '<items>', None, None, None) await scheduler.report(report) await scheduler.stop() # flushes reports assert client.received == [ (MessageType.Ack, { 'schedule_id': 'ID', 'status': 'success' }), (MessageType.Report, report), ]
async def test_reply_to_suite_message(): class MockSerializer: @staticmethod def serialize_suite(suite_items): return suite_items settings = MockSettings({}) client = MockClient(settings) suite_items = [ SuiteItem( 'test', Location('tests/IT/stub/stub_A.py', 'stub_A', 'TestClass', 'test_A', 1)) ] scheduler = Scheduler(settings, client, suite_items, 'my_worker_id', MockSerializer) await scheduler.on_server_message(MessageType.Suite.value, None) assert client.received == [ (MessageType.Suite, suite_items), ] await scheduler.stop()
async def test_successful_server_communication(config, mock_server): os.environ['MY_CI'] = 'true' settings = MockSettings({ 'api_domain': mock_server.url, 'api_key': 'api_key', 'api_retry_limit': '1', 'api_wait_limit': '0', 'build_dir': '/app', 'build_id': config['build']['id'], 'build_job': 'job', 'enabled': True, 'vcs_branch': 'master', 'vcs_repo': 'github.com/myrepo', 'vcs_revision': 'asd43da', 'vcs_revision_message': 'my commit', }) client = Client(settings) client.subscribe(settings) suite_items = [ SuiteItem( 'test', Location('tests/IT/stub/stub_A.py', 'stub_A', 'TestClass', 'test_A', 1)), SuiteItem('test', Location('tests/IT/stub/stub_B.py', 'stub_B', 'TestClass', 'test_B', 1), tags=[Tag('my_group', False)]), SuiteItem('test', Location('tests/IT/stub/stub_C.py', 'stub_C', 'TestClass', 'test_C', 1), deps=[ SuiteItem( 'fixture', Location('tests/IT/stub/stub_fixture.py', 'fixtures', 'FixtureClass', 'test_C', 0)), ]), ] scheduler = Scheduler(settings, client, suite_items, 'my_worker_id') # (1) CONNECT await client.start() # (2) SERVER REQUESTS ENV await mock_server.send(MessageType.Envs, [{ 'name': 'CI', 'conditions': ['my_CI'], 'mapping': {} }]) # (3) CLIENT REPLIES WITH ENV await assert_received_eventually(mock_server, [ (MessageType.Envs.value, 'CI'), (MessageType.Ack.value, { 'message_num': 0, 'status': 'success' }), ]) # (4) SERVER REQUESTS CONFIG await mock_server.send(MessageType.Config, {}) # (5) CLIENT REPLIES WITH CONFIG await assert_received_eventually(mock_server, [ (MessageType.Config.value, { 'build': { 'dir': '/app', 'id': config['build']['id'], 'job': 'job', 'node': 'random-uuid', 'pool': 0, 'project': None, 'url': None }, 'client': { 'capabilities': ['fixtures', 'lifecycle_timings', 'split_by_file'], 'messages': [ 'ack', 'config', 'done', 'envs', 'error', 'report', 'schedules', 'suite' ], 'name': 'pytest-conquer', 'version': '1.0', 'workers': 1, 'worker_id': 'my_worker_id', }, 'platform': { 'name': 'python', 'version': '3.6' }, 'runner': { 'args': ['arg1'], 'name': None, 'plugins': [], 'root': None, 'version': None }, 'system': { 'context': {}, 'cpus': 3, 'os': 'Linux', 'os_version': '1.42', 'provider': 'CI', 'ram': 17179869184 }, 'vcs': { 'branch': 'master', 'pr': None, 'repo': 'github.com/myrepo', 'revision': 'asd43da', 'revision_message': 'my commit', 'tag': None, 'type': 'git' }, }), (MessageType.Ack.value, { 'message_num': 1, 'status': 'success' }), ]) # (6) SERVER REQUESTS SUITE await mock_server.send(MessageType.Suite, {}) # (7) CLIENT SENDS SUITE await assert_received_eventually(mock_server, [ (MessageType.Suite.value, { 'items': [ { 'type': 'test', 'location': { 'file': 'tests/IT/stub/stub_A.py', 'func': 'test_A', 'module': 'stub_A', 'class': 'TestClass', 'line': 1 } }, { 'type': 'test', 'location': { 'file': 'tests/IT/stub/stub_B.py', 'func': 'test_B', 'module': 'stub_B', 'class': 'TestClass', 'line': 1 }, 'tags': [{ 'group': 'my_group' }] }, { 'type': 'test', 'location': { 'file': 'tests/IT/stub/stub_C.py', 'func': 'test_C', 'module': 'stub_C', 'class': 'TestClass', 'line': 1 }, 'deps': [{ 'type': 'fixture', 'location': { 'file': 'tests/IT/stub/stub_fixture.py', 'func': 'test_C', 'module': 'fixtures', 'class': 'FixtureClass' } }] }, ], }), (MessageType.Ack.value, { 'message_num': 2, 'status': 'success' }), ]) # (8) SERVER SENDS SCHEDULE #1 await mock_server.send(MessageType.Schedules, [{ 'id': '0', 'items': [ { 'file': 'tests/IT/stub/stub_A.py' }, { 'file': 'tests/IT/stub/stub_B.py' }, ], }]) await assert_received_eventually(mock_server, [ (MessageType.Ack.value, { 'message_num': 3, 'status': 'success' }), ]) assert await scheduler.next() == Schedule('0', [ ScheduleItem('tests/IT/stub/stub_A.py'), ScheduleItem('tests/IT/stub/stub_B.py'), ]) # (9) CLIENT SENDS REPORT #1 await scheduler.report( Report('0', [ ReportItem( 'test', Location('tests/IT/stub/stub_A.py', 'stub_A', 'TestClass', 'test_A', 3), 'failed', Failure('AssertionError', 'assert 1 + 1 == 4'), time, time), ReportItem( 'test', Location('tests/IT/stub/stub_B.py', 'stub_B', 'TestClass', 'test_B', 1), 'passed', None, time, time), ], time, time, time)) await assert_received_eventually(mock_server, [ (MessageType.Ack.value, { 'schedule_id': '0', 'status': 'success' }), (MessageType.Report.value, { 'schedule_id': '0', 'items': [{ 'type': 'test', 'location': { 'file': 'tests/IT/stub/stub_A.py', 'func': 'test_A', 'module': 'stub_A', 'class': 'TestClass', 'line': 3 }, 'status': 'failed', 'started_at': '2000-01-01T00:00:00.000Z', 'finished_at': '2000-01-01T00:00:00.000Z', 'error': { 'type': 'AssertionError', 'message': 'assert 1 + 1 == 4' }, }, { 'type': 'test', 'location': { 'file': 'tests/IT/stub/stub_B.py', 'func': 'test_B', 'module': 'stub_B', 'class': 'TestClass', 'line': 1 }, 'status': 'passed', 'started_at': '2000-01-01T00:00:00.000Z', 'finished_at': '2000-01-01T00:00:00.000Z', }], 'pending_at': '2000-01-01T00:00:00.000Z', 'started_at': '2000-01-01T00:00:00.000Z', 'finished_at': '2000-01-01T00:00:00.000Z', }), ]) # (10) SERVER SENDS SCHEDULE #2 await mock_server.send(MessageType.Schedules, [{ 'id': '1', 'items': [ { 'file': 'tests/IT/stub/stub_C.py' }, ], }]) await assert_received_eventually(mock_server, [ (MessageType.Ack.value, { 'message_num': 4, 'status': 'success' }), ]) assert await scheduler.next() == Schedule('1', [ ScheduleItem('tests/IT/stub/stub_C.py'), ]) # (12) CLIENT SENDS REPORT #2 await scheduler.report( Report('1', [ ReportItem( 'test', Location('tests/IT/stub/stub_C.py', 'stub_C', 'TestClass', 'test_C', 1), 'passed', None, time, time), ], time, time, time)) await assert_received_eventually(mock_server, [ (MessageType.Ack.value, { 'schedule_id': '1', 'status': 'success' }), (MessageType.Report.value, { 'schedule_id': '1', 'items': [{ 'type': 'test', 'location': { 'file': 'tests/IT/stub/stub_C.py', 'func': 'test_C', 'module': 'stub_C', 'class': 'TestClass', 'line': 1 }, 'status': 'passed', 'started_at': '2000-01-01T00:00:00.000Z', 'finished_at': '2000-01-01T00:00:00.000Z', }], 'pending_at': '2000-01-01T00:00:00.000Z', 'started_at': '2000-01-01T00:00:00.000Z', 'finished_at': '2000-01-01T00:00:00.000Z', }), ]) # (13) SERVER SENDS DONE await mock_server.send(MessageType.Done, {}) await asyncio.sleep(0.1) assert scheduler.more is False # (14) SHUTDOWN await scheduler.stop() await client.stop()