Skip to content

Commit 54b31c6

Browse files
committed
Add unit test cases for benchmark
1 parent a406614 commit 54b31c6

File tree

5 files changed

+316
-1
lines changed

5 files changed

+316
-1
lines changed

Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ setup-local-dev: poetry-install install-hooks ## Setup the local environment
2222
test: ## Run locally pytest with coverage
2323
pytest . -vv -p no:warnings --cov=. --cov-report=xml --cov-report=html
2424

25+
test-local: ## Run pytest with coverage
26+
pytest . -vv -p no:warnings --cov=.
27+
2528
check: ## Run isort black and pylint in all files
2629
isort src
2730
black src

pyproject.toml

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ python_version = "3.10"
5757
strict_optional = true
5858
strict = true
5959

60+
[project]
61+
project_urls = { "GitHub" = "https://github.com/iplitharas/pycompile" }
62+
6063

6164

6265

pytest.ini

-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
[pytest]
2-
addopts = --cov=./tests --cov-config=.coveragerc
32
norecursedirs = src/examples

tests/conftest.py

+19
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,25 @@ def sample_python_file_fixture(tmp_path: Path) -> Path:
2424
return sample_folder
2525

2626

27+
@pytest.fixture
28+
def sample_python_file_with_test_fixture(tmp_path: Path) -> Path:
29+
"""
30+
Pytest fixture to create a sample `.py` file with a corresponding
31+
and return's test file and return its parent folder path.
32+
"""
33+
# Create a sample folder within the `temp_path`
34+
sample_folder = tmp_path / "sample"
35+
sample_folder.mkdir()
36+
# Create a sample file within the sample folder
37+
python_file = sample_folder / "hello.py"
38+
content = r"print('Im a python module')"
39+
python_file.write_text(content)
40+
test_file = sample_folder / "test_hello.py"
41+
content = r"def test_hello():" r" assert True"
42+
test_file.write_text(content)
43+
return sample_folder
44+
45+
2746
@pytest.fixture
2847
def sample_files_fixture(tmp_path: Path) -> Path:
2948
"""

tests/unit/test_benchmark.py

+291
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
"""
2+
Test cases for the `Benchmark`
3+
"""
4+
import logging
5+
from unittest.mock import ANY, MagicMock, call, patch
6+
7+
from src import CythonWrapper, NuitkaWrapper
8+
from src.benchmark import Benchmark
9+
10+
MODULE = "src.benchmark"
11+
12+
13+
@patch(MODULE + ".run_pytest")
14+
@patch(MODULE + ".decorate_functions")
15+
def test_benchmark_run_cpu_bench(
16+
mocked_decorate_functions,
17+
mocked_run_pytest,
18+
sample_python_file_with_test_fixture,
19+
caplog,
20+
):
21+
"""
22+
Given one `.py` file with a test file within a directory
23+
When we invoke the `cpu_bench` from `Benchmark`
24+
Then we expect to see the `cpu_bench` in the logs,
25+
the `decorate_functions`
26+
and the run_pytest to be called once.
27+
"""
28+
# Given
29+
caplog.clear()
30+
caplog.set_level(logging.INFO)
31+
sample_folder = sample_python_file_with_test_fixture
32+
assert len(list(sample_folder.iterdir())) == 2
33+
# When
34+
Benchmark.cpu_bench(input_path=sample_folder, engine="python")
35+
# Then
36+
assert "CPU benchmark using:`python`" in caplog.text
37+
mocked_decorate_functions.assert_called_once()
38+
mocked_run_pytest.assert_called_once()
39+
40+
41+
@patch(MODULE + ".run_pytest")
42+
@patch(MODULE + ".decorate_functions")
43+
def test_benchmark_run_memory_bench(
44+
mocked_decorate_functions,
45+
mocked_run_pytest,
46+
sample_python_file_with_test_fixture,
47+
caplog,
48+
):
49+
"""
50+
Given one `.py` file with a test file within a directory
51+
When we invoke the `mem_bench` from `Benchmark`
52+
Then we expect to see the `mem_bench` in the logs,
53+
the `decore_functions` and the `run_pytest` be called once
54+
"""
55+
# Given
56+
caplog.clear()
57+
caplog.set_level(logging.INFO)
58+
sample_folder = sample_python_file_with_test_fixture
59+
assert len(list(sample_folder.iterdir())) == 2
60+
# When
61+
Benchmark.mem_bench(
62+
input_path=sample_folder, prof_func_name="test", engine="python"
63+
)
64+
# Then
65+
assert "Memory benchmark using:`python`" in caplog.text
66+
mocked_decorate_functions.assert_called_once()
67+
mocked_run_pytest.assert_called_once()
68+
69+
70+
def test_benchmark_start_with_bench_type_both_and_without_compiling(
71+
sample_python_file_with_test_fixture, caplog
72+
):
73+
"""
74+
Given one `.py` file with a test file within a directory.
75+
When we invoke the `start` method with an empty compilers list
76+
and a `bench_type` of `both`
77+
Then we expect only a mem and cpu benchmark to be executed.
78+
"""
79+
# Given
80+
caplog.clear()
81+
caplog.set_level(logging.INFO)
82+
sample_folder = sample_python_file_with_test_fixture
83+
assert len(list(sample_folder.iterdir())) == 2
84+
# When
85+
benchmark = Benchmark(input_path=sample_folder)
86+
benchmark.start(bench_type="both", compilers=[])
87+
# Then
88+
assert "Memory benchmark" in caplog.text
89+
assert "CPU benchmark" in caplog.text
90+
91+
92+
def test_benchmark_start_with_bench_type_both_and_with_cython_compiling(
93+
sample_python_file_with_test_fixture, caplog
94+
):
95+
"""
96+
Given one `.py` file with a test file within a directory.
97+
When we invoke the `start` method with compilers Cython
98+
and a `bench_type` of `both`
99+
Then we expect only a mem and cpu benchmark to be executed twice
100+
one for python and one for cython.
101+
"""
102+
# Given
103+
caplog.clear()
104+
caplog.set_level(logging.INFO)
105+
sample_folder = sample_python_file_with_test_fixture
106+
assert len(list(sample_folder.iterdir())) == 2
107+
# When
108+
benchmark = Benchmark(input_path=sample_folder)
109+
benchmark.mem_bench = MagicMock()
110+
benchmark.cpu_bench = MagicMock()
111+
benchmark._compile = MagicMock()
112+
benchmark.start(bench_type="both", compilers=[CythonWrapper()])
113+
# Then
114+
benchmark._compile.assert_called_once()
115+
benchmark.mem_bench.assert_has_calls((ANY, ANY), any_order=True)
116+
benchmark.cpu_bench.assert_has_calls((ANY, ANY), any_order=True)
117+
118+
119+
def test_benchmark_start_with_bench_type_both_and_with_cython__and_nuitka_compiling(
120+
sample_python_file_with_test_fixture, caplog
121+
):
122+
"""
123+
Given one `.py` file with a test file within a directory.
124+
When we invoke the `start` method with compilers Cython and Nuitka
125+
and a `bench_type` of `both`
126+
Then we expect only a mem and cpu benchmark to be executed three times
127+
one for python, one for cython and one for nuitka.
128+
"""
129+
# Given
130+
caplog.clear()
131+
caplog.set_level(logging.INFO)
132+
sample_folder = sample_python_file_with_test_fixture
133+
assert len(list(sample_folder.iterdir())) == 2
134+
# When
135+
benchmark = Benchmark(input_path=sample_folder)
136+
benchmark.mem_bench = MagicMock()
137+
benchmark.cpu_bench = MagicMock()
138+
benchmark._compile = MagicMock()
139+
benchmark.start(
140+
bench_type="both", compilers=[CythonWrapper(), NuitkaWrapper()]
141+
)
142+
# Then
143+
benchmark._compile.assert_has_calls((ANY, ANY), any_order=True)
144+
benchmark.mem_bench.assert_has_calls((ANY, ANY, ANY), any_order=True)
145+
benchmark.cpu_bench.assert_has_calls((ANY, ANY, ANY), any_order=True)
146+
147+
148+
def test_benchmark_start_with_bench_type_memory_and_without_compiling(
149+
sample_python_file_with_test_fixture, caplog
150+
):
151+
"""
152+
Given one `.py` file with a test file within a directory.
153+
When we invoke the `start` method with an empty compilers list
154+
and a `bench_type` of `memory`
155+
Then we expect only a mem benchmark to be executed.
156+
"""
157+
# Given
158+
caplog.clear()
159+
caplog.set_level(logging.INFO)
160+
sample_folder = sample_python_file_with_test_fixture
161+
# When
162+
benchmark = Benchmark(input_path=sample_folder)
163+
benchmark.start(bench_type="memory", compilers=[])
164+
# Then
165+
assert "Memory benchmark" in caplog.text
166+
assert "CPU benchmark" not in caplog.text
167+
168+
169+
def test_benchmark_start_with_bench_type_memory_and_with_cython__and_nuitka_compiling(
170+
sample_python_file_with_test_fixture, caplog
171+
):
172+
"""
173+
Given one `.py` file with a test file within a directory.
174+
When we invoke the `start` method with compilers Cython
175+
and a `bench_type` of `memory`
176+
Then we expect only a mem benchmark to be executed the times
177+
"""
178+
# Given
179+
caplog.clear()
180+
caplog.set_level(logging.INFO)
181+
sample_folder = sample_python_file_with_test_fixture
182+
# When
183+
benchmark = Benchmark(input_path=sample_folder)
184+
benchmark.mem_bench = MagicMock()
185+
benchmark.cpu_bench = MagicMock()
186+
benchmark._compile = MagicMock()
187+
benchmark.start(
188+
bench_type="memory", compilers=[CythonWrapper(), NuitkaWrapper()]
189+
)
190+
# Then
191+
benchmark._compile.assert_has_calls((ANY, ANY), any_order=True)
192+
benchmark.mem_bench.assert_has_calls((ANY, ANY, ANY), any_order=True)
193+
benchmark.cpu_bench.assert_not_called()
194+
195+
196+
def test_benchmark_start_with_bench_type_memory_and_with_cython_compiling(
197+
sample_python_file_with_test_fixture, caplog
198+
):
199+
"""
200+
Given one `.py` file with a test file within a directory.
201+
When we invoke the `start` method with compilers Cython
202+
and a `bench_type` of `memory`
203+
Then we expect only a mem benchmark to be executed twice
204+
"""
205+
# Given
206+
caplog.clear()
207+
caplog.set_level(logging.INFO)
208+
sample_folder = sample_python_file_with_test_fixture
209+
# When
210+
benchmark = Benchmark(input_path=sample_folder)
211+
benchmark.mem_bench = MagicMock()
212+
benchmark.cpu_bench = MagicMock()
213+
benchmark._compile = MagicMock()
214+
benchmark.start(bench_type="memory", compilers=[CythonWrapper()])
215+
# Then
216+
benchmark._compile.assert_called_once()
217+
benchmark.mem_bench.assert_has_calls((ANY, ANY), any_order=True)
218+
benchmark.cpu_bench.assert_not_called()
219+
220+
221+
def test_benchmark_start_with_bench_type_cpu_and_without_compiling(
222+
sample_python_file_with_test_fixture, caplog
223+
):
224+
"""
225+
Given one `.py` file with a test file within a directory.
226+
When we invoke the `start` method with an empty compilers list
227+
and a `bench_type` of `cpu`
228+
Then we expect only a cpu benchmark to be executed.
229+
"""
230+
# Given
231+
caplog.clear()
232+
caplog.set_level(logging.INFO)
233+
sample_folder = sample_python_file_with_test_fixture
234+
# When
235+
benchmark = Benchmark(input_path=sample_folder)
236+
benchmark.start(bench_type="cpu", compilers=[])
237+
# Then
238+
assert "Memory benchmark" not in caplog.text
239+
assert "CPU benchmark" in caplog.text
240+
241+
242+
def test_benchmark_start_with_bench_type_cpu_and_with_cython_compiling(
243+
sample_python_file_with_test_fixture, caplog
244+
):
245+
"""
246+
Given one `.py` file with a test file within a directory.
247+
When we invoke the `start` method with compilers Cython
248+
and a `bench_type` of `cpu`
249+
Then we expect only a cpu benchmark to be executed twice
250+
"""
251+
# Given
252+
caplog.clear()
253+
caplog.set_level(logging.INFO)
254+
sample_folder = sample_python_file_with_test_fixture
255+
# When
256+
benchmark = Benchmark(input_path=sample_folder)
257+
benchmark.mem_bench = MagicMock()
258+
benchmark.cpu_bench = MagicMock()
259+
benchmark._compile = MagicMock()
260+
benchmark.start(bench_type="cpu", compilers=[CythonWrapper()])
261+
# Then
262+
benchmark._compile.assert_called_once()
263+
benchmark.cpu_bench.assert_has_calls((ANY, ANY), any_order=True)
264+
benchmark.mem_bench.assert_not_called()
265+
266+
267+
def test_benchmark_start_with_bench_type_cpu_and_with_cython_and_nuitka_compiling(
268+
sample_python_file_with_test_fixture, caplog
269+
):
270+
"""
271+
Given one `.py` file with a test file within a directory.
272+
When we invoke the `start` method with compilers Cython and Nuitka
273+
and a `bench_type` of `cpu`
274+
Then we expect only a cpu benchmark to be executed three times
275+
"""
276+
# Given
277+
caplog.clear()
278+
caplog.set_level(logging.INFO)
279+
sample_folder = sample_python_file_with_test_fixture
280+
# When
281+
benchmark = Benchmark(input_path=sample_folder)
282+
benchmark.mem_bench = MagicMock()
283+
benchmark.cpu_bench = MagicMock()
284+
benchmark._compile = MagicMock()
285+
benchmark.start(
286+
bench_type="cpu", compilers=[CythonWrapper(), NuitkaWrapper()]
287+
)
288+
# Then
289+
benchmark._compile.assert_has_calls((ANY, ANY), any_order=True)
290+
benchmark.cpu_bench.assert_has_calls((ANY, ANY, ANY), any_order=True)
291+
benchmark.mem_bench.assert_not_called()

0 commit comments

Comments
 (0)