From 9124019eff2cc949861c53c16727aadc35a3e731 Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Tue, 12 Jan 2021 22:05:00 +0900 Subject: [PATCH 1/8] feature: add go test subset plugin --- launchable/test_runners/go_test.py | 12 +++++ tests/commands/test_record_tests_go_test.py | 59 +++++++++++++++++++++ tests/data/go_test/report.xml | 12 +++++ tests/data/go_test/subset_result.json | 6 +++ 4 files changed, 89 insertions(+) create mode 100644 launchable/test_runners/go_test.py create mode 100644 tests/commands/test_record_tests_go_test.py create mode 100644 tests/data/go_test/report.xml create mode 100644 tests/data/go_test/subset_result.json diff --git a/launchable/test_runners/go_test.py b/launchable/test_runners/go_test.py new file mode 100644 index 000000000..ca321d8a7 --- /dev/null +++ b/launchable/test_runners/go_test.py @@ -0,0 +1,12 @@ +from junitparser import TestCase, TestSuite +import sys +from . import launchable + + +@launchable.subset +def subset(client): + for case in sys.stdin: + # Aboid last line such s `ok github.com/launchableinc/rocket-car-gotest 0.268s` + if not ' ' in case: + client.test_path({'type': 'testcase', 'name': case.rstrip('\n')}) + client.run() diff --git a/tests/commands/test_record_tests_go_test.py b/tests/commands/test_record_tests_go_test.py new file mode 100644 index 000000000..3ac1edc2e --- /dev/null +++ b/tests/commands/test_record_tests_go_test.py @@ -0,0 +1,59 @@ +from unittest import TestCase, mock +from nose.tools import eq_, ok_ +from click.testing import CliRunner +from test.support import captured_stdin + +import os +import json +from pathlib import Path +import gzip + +from launchable.__main__ import main + + +class GoTestTest(TestCase): + launchable_token = 'v1:launchableinc/mothership:auth-token-sample' + session = '/intake/organizations/launchableinc/workspaces/mothership/builds/123/test_sessions/16' + test_files_dir = Path(__file__).parent.joinpath( + '../data/go_test/').resolve() + + def setUp(self): + self.maxDiff = None + os.environ['LAUNCHABLE_TOKEN'] = self.launchable_token + + @mock.patch('requests.request') + def test_subset(self, mock_post): + runner = CliRunner() + pipe = "TestExample1\nTestExample2\nTestExample3\nTestExample4\nok github.com/launchableinc/rocket-car-gotest 0.268s" + result = runner.invoke(main, [ + 'subset', '--target', '10%', '--session', self.session, 'go_test'], input=pipe) + + self.assertEqual(result.exit_code, 0) + + for (args, kwargs) in mock_post.call_args_list: + if kwargs['data']: + data = kwargs['data'] + + result_file_path = self.test_files_dir.joinpath('subset_result.json') + with result_file_path.open() as json_file: + expected = json.load(json_file) + self.assertDictEqual(json.loads(data), expected) + + # @mock.patch('requests.request') + # def test_record_test_minitest(self, mock_post): + # runner = CliRunner() + # result = runner.invoke(main, ['record', 'tests', '--session', self.session, 'go_test', str(self.test_files_dir) + "/"]) + # self.assertEqual(result.exit_code, 0) + # for (args, kwargs) in mock_post.call_args_list: + # if kwargs['data']: + # data = kwargs['data'] + # zipped_payload = b''.join(data) + # payload = json.loads(gzip.decompress(zipped_payload).decode()) + # with self.result_file_path.open() as json_file: + # expected = json.load(json_file) + + # # Normalize events order that depends on shell glob implementation + # payload['events'] = sorted(payload['events'], key=lambda c: c['testPath'][0]['name'] + c['testPath'][1]['name']) + # expected['events'] = sorted(expected['events'], key=lambda c: c['testPath'][0]['name'] + c['testPath'][1]['name']) + + # self.assertDictEqual(payload, expected) diff --git a/tests/data/go_test/report.xml b/tests/data/go_test/report.xml new file mode 100644 index 000000000..26c9fe603 --- /dev/null +++ b/tests/data/go_test/report.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/data/go_test/subset_result.json b/tests/data/go_test/subset_result.json new file mode 100644 index 000000000..164c3f30a --- /dev/null +++ b/tests/data/go_test/subset_result.json @@ -0,0 +1,6 @@ +{"session": {"id": "16"}, + "target": 0.1, + "testPaths": [{"name": "TestExample1", "type": "testcase"}, + {"name": "TestExample2", "type": "testcase"}, + {"name": "TestExample3", "type": "testcase"}, + {"name": "TestExample4", "type": "testcase"}]} \ No newline at end of file From b95ad448a8ee61786acdd2163d606d0de03f3be8 Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Tue, 12 Jan 2021 22:10:01 +0900 Subject: [PATCH 2/8] feature: add go test record test plugin --- launchable/test_runners/go_test.py | 10 ++++- tests/commands/test_record_tests_go_test.py | 49 +++++++++++++-------- tests/data/go_test/record_test_result.json | 6 +++ 3 files changed, 46 insertions(+), 19 deletions(-) create mode 100644 tests/data/go_test/record_test_result.json diff --git a/launchable/test_runners/go_test.py b/launchable/test_runners/go_test.py index ca321d8a7..c20d9e541 100644 --- a/launchable/test_runners/go_test.py +++ b/launchable/test_runners/go_test.py @@ -1,5 +1,5 @@ -from junitparser import TestCase, TestSuite import sys +import click from . import launchable @@ -10,3 +10,11 @@ def subset(client): if not ' ' in case: client.test_path({'type': 'testcase', 'name': case.rstrip('\n')}) client.run() + + +@click.argument('source_roots', required=True, nargs=-1) +@launchable.record.tests +def record_tests(client, source_roots): + for root in source_roots: + client.scan(root, "*.xml") + client.run() diff --git a/tests/commands/test_record_tests_go_test.py b/tests/commands/test_record_tests_go_test.py index 3ac1edc2e..e7685f962 100644 --- a/tests/commands/test_record_tests_go_test.py +++ b/tests/commands/test_record_tests_go_test.py @@ -39,21 +39,34 @@ def test_subset(self, mock_post): expected = json.load(json_file) self.assertDictEqual(json.loads(data), expected) - # @mock.patch('requests.request') - # def test_record_test_minitest(self, mock_post): - # runner = CliRunner() - # result = runner.invoke(main, ['record', 'tests', '--session', self.session, 'go_test', str(self.test_files_dir) + "/"]) - # self.assertEqual(result.exit_code, 0) - # for (args, kwargs) in mock_post.call_args_list: - # if kwargs['data']: - # data = kwargs['data'] - # zipped_payload = b''.join(data) - # payload = json.loads(gzip.decompress(zipped_payload).decode()) - # with self.result_file_path.open() as json_file: - # expected = json.load(json_file) - - # # Normalize events order that depends on shell glob implementation - # payload['events'] = sorted(payload['events'], key=lambda c: c['testPath'][0]['name'] + c['testPath'][1]['name']) - # expected['events'] = sorted(expected['events'], key=lambda c: c['testPath'][0]['name'] + c['testPath'][1]['name']) - - # self.assertDictEqual(payload, expected) + @mock.patch('requests.request') + def test_record_tests(self, mock_post): + runner = CliRunner() + result = runner.invoke(main, ['record', 'tests', '--session', + self.session, 'go_test', str(self.test_files_dir) + "/"]) + self.assertEqual(result.exit_code, 0) + + for (args, kwargs) in mock_post.call_args_list: + if kwargs['data']: + data = kwargs['data'] + zipped_payload = b''.join(data) + payload = json.loads(gzip.decompress(zipped_payload).decode()) + + result_file_path = self.test_files_dir.joinpath( + 'record_test_result.json') + with result_file_path.open() as json_file: + expected = json.load(json_file) + + # Normalize events order that depends on shell glob implementation + payload['events'] = sorted( + payload['events'], key=lambda c: c['testPath'][0]['name']) + expected['events'] = sorted( + expected['events'], key=lambda c: c['testPath'][0]['name']) + + # Remove timestamp because it depends on the machine clock + for c in payload['events']: + del c['created_at'] + for c in expected['events']: + del c['created_at'] + + self.assertDictEqual(payload, expected) diff --git a/tests/data/go_test/record_test_result.json b/tests/data/go_test/record_test_result.json new file mode 100644 index 000000000..8ca42985a --- /dev/null +++ b/tests/data/go_test/record_test_result.json @@ -0,0 +1,6 @@ +{"events": [ + {"type": "case", "testPath": [{"type": "class", "name": "rocket-car-gotest"}, {"type": "testcase", "name": "TestExample1", "_lineno": null}], "duration": 0.0, "status": 1, "stdout": "", "stderr": "", "created_at": "2021-01-12T13:12:33.410391+00:00", "data": null}, + {"type": "case", "testPath": [{"type": "class", "name": "rocket-car-gotest"}, {"type": "testcase", "name": "TestExample2", "_lineno": null}], "duration": 3.0, "status": 1, "stdout": "", "stderr": "", "created_at": "2021-01-12T13:12:33.410811+00:00", "data": null}, + {"type": "case", "testPath": [{"type": "class", "name": "rocket-car-gotest"}, {"type": "testcase", "name": "TestExample3", "_lineno": null}], "duration": 0.0, "status": 1, "stdout": "", "stderr": "", "created_at": "2021-01-12T13:12:33.410874+00:00", "data": null}, + {"type": "case", "testPath": [{"type": "class", "name": "rocket-car-gotest"}, {"type": "testcase", "name": "TestExample4", "_lineno": null}], "duration": 2.0, "status": 1, "stdout": "", "stderr": "", "created_at": "2021-01-12T13:12:33.410917+00:00", "data": null} +]} \ No newline at end of file From 7475c652b5e6dfbd3897d9d3a80eb5f01c3ca18b Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Tue, 12 Jan 2021 22:32:46 +0900 Subject: [PATCH 3/8] fix: python 3.5 --- tests/commands/test_record_tests_go_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/commands/test_record_tests_go_test.py b/tests/commands/test_record_tests_go_test.py index e7685f962..305f8a0e5 100644 --- a/tests/commands/test_record_tests_go_test.py +++ b/tests/commands/test_record_tests_go_test.py @@ -37,7 +37,7 @@ def test_subset(self, mock_post): result_file_path = self.test_files_dir.joinpath('subset_result.json') with result_file_path.open() as json_file: expected = json.load(json_file) - self.assertDictEqual(json.loads(data), expected) + self.assertDictEqual(json.loads(data.decode()), expected) @mock.patch('requests.request') def test_record_tests(self, mock_post): From 0d7743e18a85309d0dae810a3f38113b65b07f6b Mon Sep 17 00:00:00 2001 From: awilkes Date: Tue, 12 Jan 2021 15:52:19 -0700 Subject: [PATCH 4/8] Update launchable/test_runners/go_test.py --- launchable/test_runners/go_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launchable/test_runners/go_test.py b/launchable/test_runners/go_test.py index c20d9e541..cb78cfe41 100644 --- a/launchable/test_runners/go_test.py +++ b/launchable/test_runners/go_test.py @@ -6,7 +6,7 @@ @launchable.subset def subset(client): for case in sys.stdin: - # Aboid last line such s `ok github.com/launchableinc/rocket-car-gotest 0.268s` + # Avoid last line such as `ok github.com/launchableinc/rocket-car-gotest 0.268s` if not ' ' in case: client.test_path({'type': 'testcase', 'name': case.rstrip('\n')}) client.run() From ff37285095bc57a96e66c5f023eed36f40cec0c4 Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Wed, 13 Jan 2021 18:37:39 +0900 Subject: [PATCH 5/8] feature: subset output format --- launchable/test_runners/go_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launchable/test_runners/go_test.py b/launchable/test_runners/go_test.py index cb78cfe41..e2a7dd975 100644 --- a/launchable/test_runners/go_test.py +++ b/launchable/test_runners/go_test.py @@ -2,13 +2,14 @@ import click from . import launchable - @launchable.subset def subset(client): for case in sys.stdin: # Avoid last line such as `ok github.com/launchableinc/rocket-car-gotest 0.268s` if not ' ' in case: client.test_path({'type': 'testcase', 'name': case.rstrip('\n')}) + + client.formatter = lambda t: "^{}$|".format(t) client.run() From e9be436b20ee605a58d46ec4355b64f6c7b1392f Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Wed, 13 Jan 2021 19:27:17 +0900 Subject: [PATCH 6/8] feature: intoroduce seperator formatter --- launchable/commands/subset.py | 12 ++++++++++-- launchable/test_runners/go_test.py | 3 ++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/launchable/commands/subset.py b/launchable/commands/subset.py index 04be77887..46f25a463 100644 --- a/launchable/commands/subset.py +++ b/launchable/commands/subset.py @@ -52,6 +52,7 @@ def __init__(self): self.test_paths = [] # TODO: robustness improvement. self._formatter = Optimize.default_formatter + self._separator = "\n" @staticmethod def default_formatter(x: TestPath): @@ -74,6 +75,14 @@ def formatter(self) -> Callable[[TestPath], str]: def formatter(self, v: Callable[[TestPath], str]): self._formatter = v + @property + def separator(self) -> str: + return self._separator + + @separator.setter + def separator(self, s: str): + self._separator = s + def test_path(self, path: TestPathLike): """register one test""" self.test_paths.append(self.to_test_path(path)) @@ -160,7 +169,6 @@ def run(self): # regardless of whether we managed to talk to the service # we produce test names - for t in output: - click.echo(self.formatter(t)) + click.echo(self.separator.join(self.formatter(t) for t in output)) context.obj = Optimize() diff --git a/launchable/test_runners/go_test.py b/launchable/test_runners/go_test.py index e2a7dd975..5a2866e82 100644 --- a/launchable/test_runners/go_test.py +++ b/launchable/test_runners/go_test.py @@ -9,7 +9,8 @@ def subset(client): if not ' ' in case: client.test_path({'type': 'testcase', 'name': case.rstrip('\n')}) - client.formatter = lambda t: "^{}$|".format(t) + client.formatter = lambda t: "^{}$".format(t) + client.separator = '|' client.run() From 433d3d9aa5689565c15d2e296e8de71b29c53e7b Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Wed, 13 Jan 2021 22:07:20 +0900 Subject: [PATCH 7/8] fix: test_path --- launchable/test_runners/go_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launchable/test_runners/go_test.py b/launchable/test_runners/go_test.py index 5a2866e82..d183875a4 100644 --- a/launchable/test_runners/go_test.py +++ b/launchable/test_runners/go_test.py @@ -7,9 +7,9 @@ def subset(client): for case in sys.stdin: # Avoid last line such as `ok github.com/launchableinc/rocket-car-gotest 0.268s` if not ' ' in case: - client.test_path({'type': 'testcase', 'name': case.rstrip('\n')}) + client.test_path([{'type': 'testcase', 'name': case.rstrip('\n')}]) - client.formatter = lambda t: "^{}$".format(t) + client.formatter = lambda x: "^{}$".format(x[0]['name']) client.separator = '|' client.run() From bd4f2a87880f309722b63f1c7e8b20b95a010dc6 Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Wed, 13 Jan 2021 23:39:46 +0900 Subject: [PATCH 8/8] fix: test data --- tests/data/go_test/subset_result.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/data/go_test/subset_result.json b/tests/data/go_test/subset_result.json index 164c3f30a..25067d8d7 100644 --- a/tests/data/go_test/subset_result.json +++ b/tests/data/go_test/subset_result.json @@ -1,6 +1,6 @@ {"session": {"id": "16"}, "target": 0.1, - "testPaths": [{"name": "TestExample1", "type": "testcase"}, - {"name": "TestExample2", "type": "testcase"}, - {"name": "TestExample3", "type": "testcase"}, - {"name": "TestExample4", "type": "testcase"}]} \ No newline at end of file + "testPaths": [[{"name": "TestExample1", "type": "testcase"}], + [{"name": "TestExample2", "type": "testcase"}], + [{"name": "TestExample3", "type": "testcase"}], + [{"name": "TestExample4", "type": "testcase"}]]} \ No newline at end of file