Skip to content

Commit de61dda

Browse files
committed
Add option to repeatly execute betterproto operations in test, to evaluate performance
1 parent 5e2d9fe commit de61dda

File tree

2 files changed

+67
-57
lines changed

2 files changed

+67
-57
lines changed

betterproto/tests/test_inputs.py

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import pytest
66
import betterproto
77
from betterproto.tests.util import get_directories, inputs_path
8+
from collections import namedtuple
89

910
# Force pure-python implementation instead of C++, otherwise imports
1011
# break things because we can't properly reset the symbol database.
@@ -22,47 +23,13 @@
2223
reference_output_package = "betterproto.tests.output_reference"
2324

2425

25-
@pytest.mark.parametrize("test_case_name", test_case_names)
26-
def test_message_can_be_imported(test_case_name: str) -> None:
27-
importlib.import_module(
28-
f"{plugin_output_package}.{test_case_name}.{test_case_name}"
29-
)
30-
31-
32-
@pytest.mark.parametrize("test_case_name", test_case_names)
33-
def test_message_can_instantiated(test_case_name: str) -> None:
34-
plugin_module = importlib.import_module(
35-
f"{plugin_output_package}.{test_case_name}.{test_case_name}"
36-
)
37-
plugin_module.Test()
26+
TestData = namedtuple("TestData", "plugin_module, reference_module, json_data")
3827

3928

40-
@pytest.mark.parametrize("test_case_name", test_case_names)
41-
def test_message_equality(test_case_name: str) -> None:
42-
plugin_module = importlib.import_module(
43-
f"{plugin_output_package}.{test_case_name}.{test_case_name}"
44-
)
45-
message1 = plugin_module.Test()
46-
message2 = plugin_module.Test()
47-
assert message1 == message2
29+
@pytest.fixture(scope="module", params=test_case_names)
30+
def test_data(request):
31+
test_case_name = request.param
4832

49-
50-
@pytest.mark.parametrize("test_case_name", test_case_names)
51-
def test_message_json(test_case_name: str) -> None:
52-
plugin_module = importlib.import_module(
53-
f"{plugin_output_package}.{test_case_name}.{test_case_name}"
54-
)
55-
message: betterproto.Message = plugin_module.Test()
56-
reference_json_data = get_test_case_json_data(test_case_name)
57-
58-
message.from_json(reference_json_data)
59-
message_json = message.to_json(0)
60-
61-
assert json.loads(reference_json_data) == json.loads(message_json)
62-
63-
64-
@pytest.mark.parametrize("test_case_name", test_case_names)
65-
def test_binary_compatibility(test_case_name: str) -> None:
6633
# Reset the internal symbol database so we can import the `Test` message
6734
# multiple times. Ugh.
6835
sym = symbol_database.Default()
@@ -74,31 +41,64 @@ def test_binary_compatibility(test_case_name: str) -> None:
7441

7542
sys.path.append(reference_module_root)
7643

77-
# import reference message
78-
reference_module = importlib.import_module(
79-
f"{reference_output_package}.{test_case_name}.{test_case_name}_pb2"
80-
)
81-
plugin_module = importlib.import_module(
82-
f"{plugin_output_package}.{test_case_name}.{test_case_name}"
44+
yield TestData(
45+
plugin_module=importlib.import_module(
46+
f"{plugin_output_package}.{test_case_name}.{test_case_name}"
47+
),
48+
reference_module=importlib.import_module(
49+
f"{reference_output_package}.{test_case_name}.{test_case_name}_pb2"
50+
),
51+
json_data=get_test_case_json_data(test_case_name),
8352
)
8453

85-
test_data = get_test_case_json_data(test_case_name)
54+
sys.path.remove(reference_module_root)
55+
8656

87-
reference_instance = Parse(test_data, reference_module.Test())
88-
reference_binary_output = reference_instance.SerializeToString()
57+
def test_message_can_instantiated(test_data: TestData) -> None:
58+
plugin_module, *_ = test_data
59+
plugin_module.Test()
8960

90-
plugin_instance_from_json: betterproto.Message = plugin_module.Test().from_json(
91-
test_data
92-
)
93-
plugin_instance_from_binary = plugin_module.Test.FromString(reference_binary_output)
9461

95-
# # Generally this can't be relied on, but here we are aiming to match the
96-
# # existing Python implementation and aren't doing anything tricky.
97-
# # https://developers.google.com/protocol-buffers/docs/encoding#implications
98-
assert plugin_instance_from_json == plugin_instance_from_binary
99-
assert plugin_instance_from_json.to_dict() == plugin_instance_from_binary.to_dict()
62+
def test_message_equality(test_data: TestData) -> None:
63+
plugin_module, *_ = test_data
64+
message1 = plugin_module.Test()
65+
message2 = plugin_module.Test()
66+
assert message1 == message2
10067

101-
sys.path.remove(reference_module_root)
68+
69+
def test_message_json(repeat, test_data: TestData) -> None:
70+
plugin_module, _, json_data = test_data
71+
72+
for _ in range(repeat):
73+
message: betterproto.Message = plugin_module.Test()
74+
75+
message.from_json(json_data)
76+
message_json = message.to_json(0)
77+
78+
assert json.loads(json_data) == json.loads(message_json)
79+
80+
81+
def test_binary_compatibility(repeat, test_data: TestData) -> None:
82+
plugin_module, reference_module, json_data = test_data
83+
84+
reference_instance = Parse(json_data, reference_module.Test())
85+
reference_binary_output = reference_instance.SerializeToString()
86+
87+
for _ in range(repeat):
88+
plugin_instance_from_json: betterproto.Message = plugin_module.Test().from_json(
89+
json_data
90+
)
91+
plugin_instance_from_binary = plugin_module.Test.FromString(
92+
reference_binary_output
93+
)
94+
95+
# # Generally this can't be relied on, but here we are aiming to match the
96+
# # existing Python implementation and aren't doing anything tricky.
97+
# # https://developers.google.com/protocol-buffers/docs/encoding#implications
98+
assert plugin_instance_from_json == plugin_instance_from_binary
99+
assert (
100+
plugin_instance_from_json.to_dict() == plugin_instance_from_binary.to_dict()
101+
)
102102

103103

104104
"""

conftest.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import pytest
2+
3+
4+
def pytest_addoption(parser):
5+
parser.addoption("--repeat", type=int, default=1, help="repeat the operation multiple times")
6+
7+
8+
@pytest.fixture(scope="session")
9+
def repeat(request):
10+
return request.config.getoption("repeat")

0 commit comments

Comments
 (0)