From de61ddab21a9e3e34a4ffa7fd3df7fa64a594b85 Mon Sep 17 00:00:00 2001 From: James Lan Date: Tue, 19 May 2020 10:26:23 -0700 Subject: [PATCH] Add option to repeatly execute betterproto operations in test, to evaluate performance --- betterproto/tests/test_inputs.py | 120 +++++++++++++++---------------- conftest.py | 10 +++ 2 files changed, 70 insertions(+), 60 deletions(-) create mode 100644 conftest.py diff --git a/betterproto/tests/test_inputs.py b/betterproto/tests/test_inputs.py index c8fb7d3..0088d81 100644 --- a/betterproto/tests/test_inputs.py +++ b/betterproto/tests/test_inputs.py @@ -5,6 +5,7 @@ import sys import pytest import betterproto from betterproto.tests.util import get_directories, inputs_path +from collections import namedtuple # Force pure-python implementation instead of C++, otherwise imports # break things because we can't properly reset the symbol database. @@ -22,47 +23,13 @@ plugin_output_package = "betterproto.tests.output_betterproto" reference_output_package = "betterproto.tests.output_reference" -@pytest.mark.parametrize("test_case_name", test_case_names) -def test_message_can_be_imported(test_case_name: str) -> None: - importlib.import_module( - f"{plugin_output_package}.{test_case_name}.{test_case_name}" - ) +TestData = namedtuple("TestData", "plugin_module, reference_module, json_data") -@pytest.mark.parametrize("test_case_name", test_case_names) -def test_message_can_instantiated(test_case_name: str) -> None: - plugin_module = importlib.import_module( - f"{plugin_output_package}.{test_case_name}.{test_case_name}" - ) - plugin_module.Test() +@pytest.fixture(scope="module", params=test_case_names) +def test_data(request): + test_case_name = request.param - -@pytest.mark.parametrize("test_case_name", test_case_names) -def test_message_equality(test_case_name: str) -> None: - plugin_module = importlib.import_module( - f"{plugin_output_package}.{test_case_name}.{test_case_name}" - ) - message1 = plugin_module.Test() - message2 = plugin_module.Test() - assert message1 == message2 - - -@pytest.mark.parametrize("test_case_name", test_case_names) -def test_message_json(test_case_name: str) -> None: - plugin_module = importlib.import_module( - f"{plugin_output_package}.{test_case_name}.{test_case_name}" - ) - message: betterproto.Message = plugin_module.Test() - reference_json_data = get_test_case_json_data(test_case_name) - - message.from_json(reference_json_data) - message_json = message.to_json(0) - - assert json.loads(reference_json_data) == json.loads(message_json) - - -@pytest.mark.parametrize("test_case_name", test_case_names) -def test_binary_compatibility(test_case_name: str) -> None: # Reset the internal symbol database so we can import the `Test` message # multiple times. Ugh. sym = symbol_database.Default() @@ -74,33 +41,66 @@ def test_binary_compatibility(test_case_name: str) -> None: sys.path.append(reference_module_root) - # import reference message - reference_module = importlib.import_module( - f"{reference_output_package}.{test_case_name}.{test_case_name}_pb2" + yield TestData( + plugin_module=importlib.import_module( + f"{plugin_output_package}.{test_case_name}.{test_case_name}" + ), + reference_module=importlib.import_module( + f"{reference_output_package}.{test_case_name}.{test_case_name}_pb2" + ), + json_data=get_test_case_json_data(test_case_name), ) - plugin_module = importlib.import_module( - f"{plugin_output_package}.{test_case_name}.{test_case_name}" - ) - - test_data = get_test_case_json_data(test_case_name) - - reference_instance = Parse(test_data, reference_module.Test()) - reference_binary_output = reference_instance.SerializeToString() - - plugin_instance_from_json: betterproto.Message = plugin_module.Test().from_json( - test_data - ) - plugin_instance_from_binary = plugin_module.Test.FromString(reference_binary_output) - - # # Generally this can't be relied on, but here we are aiming to match the - # # existing Python implementation and aren't doing anything tricky. - # # https://developers.google.com/protocol-buffers/docs/encoding#implications - assert plugin_instance_from_json == plugin_instance_from_binary - assert plugin_instance_from_json.to_dict() == plugin_instance_from_binary.to_dict() sys.path.remove(reference_module_root) +def test_message_can_instantiated(test_data: TestData) -> None: + plugin_module, *_ = test_data + plugin_module.Test() + + +def test_message_equality(test_data: TestData) -> None: + plugin_module, *_ = test_data + message1 = plugin_module.Test() + message2 = plugin_module.Test() + assert message1 == message2 + + +def test_message_json(repeat, test_data: TestData) -> None: + plugin_module, _, json_data = test_data + + for _ in range(repeat): + message: betterproto.Message = plugin_module.Test() + + message.from_json(json_data) + message_json = message.to_json(0) + + assert json.loads(json_data) == json.loads(message_json) + + +def test_binary_compatibility(repeat, test_data: TestData) -> None: + plugin_module, reference_module, json_data = test_data + + reference_instance = Parse(json_data, reference_module.Test()) + reference_binary_output = reference_instance.SerializeToString() + + for _ in range(repeat): + plugin_instance_from_json: betterproto.Message = plugin_module.Test().from_json( + json_data + ) + plugin_instance_from_binary = plugin_module.Test.FromString( + reference_binary_output + ) + + # # Generally this can't be relied on, but here we are aiming to match the + # # existing Python implementation and aren't doing anything tricky. + # # https://developers.google.com/protocol-buffers/docs/encoding#implications + assert plugin_instance_from_json == plugin_instance_from_binary + assert ( + plugin_instance_from_json.to_dict() == plugin_instance_from_binary.to_dict() + ) + + """ helper methods """ diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..1727782 --- /dev/null +++ b/conftest.py @@ -0,0 +1,10 @@ +import pytest + + +def pytest_addoption(parser): + parser.addoption("--repeat", type=int, default=1, help="repeat the operation multiple times") + + +@pytest.fixture(scope="session") +def repeat(request): + return request.config.getoption("repeat")