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', ]
def mock_generate_settings(): import testandconquer.plugin # has to be inline since the module can't be loaded upfront due to pytester previous = testandconquer.plugin.create_settings testandconquer.plugin.create_settings = lambda config: MockSettings( {'enabled': True}) yield # run test testandconquer.plugin.create_settings = previous
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 __aenter__(self): # set up server self.server = MockServer() await self.server.start() # set up client self.settings['api_domain'] = self.server.url + '?primary' self.settings['api_domain_fallback'] = self.server.url + '?fallback' self.client = Client(MockSettings(self.settings)) await self.client.start() # set up subscriber self.subscriber = Subscriber() self.client.subscribe(self.subscriber) return self.client, self.server, self.subscriber
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()
def test_connection_when_server_not_reachable(self, datetime_mock, caplog, event_loop): settings = { 'api_retry_limit': '3', 'api_wait_limit': '0', 'api_domain': 'doesnot.exist:801', 'api_domain_fallback': 'doesnot.exist:802', } self.client = Client(MockSettings(settings)) with pytest.raises(SystemExit): datetime_mock.utcnow = mock.Mock(return_value=datetime(2000, 1, 1)) event_loop.run_until_complete(self.client.start()) event_loop.run_until_complete(asyncio.sleep(1)) assert warn_messages(caplog) == [ 'lost socket connection, will try to re-connect', 'lost socket connection, will try to re-connect', 'lost socket connection, will try to re-connect', 'lost socket connection, will try to re-connect', ] assert error_messages(caplog) == [ '\n' '\n' ' ' '================================================================================\n' '\n' ' [ERROR] [CONQUER] COULD NOT CONNECT:\n' '\n' ' Unable to connect to server, giving up.\n' ' Please try again and contact support if the error persists.\n' '\n' ' [Client-Name = pytest-conquer]\n' ' [Client-Version = 1.0]\n' ' [Connection-Attempt = 4]\n' ' [Connection-ID = ' + str(self.client.id) + ']\n' ' [Timestamp = 2000-01-01T00:00:00]\n' '\n' ' ' '================================================================================\n' '\n', ]
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()