Skip to content

Commit 7f0593f

Browse files
committed
Add unit tests
1 parent a53e107 commit 7f0593f

14 files changed

Lines changed: 408 additions & 7 deletions

File tree

.github/workflows/test.yml

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,41 +29,46 @@ jobs:
2929
3030
runs-on: "${{ matrix.os }}-latest"
3131

32-
env:
33-
BUNDLE_PYTHON_TESTS: ${{ matrix.bundled }}
34-
3532
steps:
3633
- uses: actions/setup-python@v5
3734
with:
3835
python-version: "${{ matrix.python }}"
3936

4037
- uses: actions/checkout@v4
4138

42-
- name: Setup cmake
39+
- name: Setup CMake
4340
uses: jwlawson/actions-setup-cmake@v2.0
4441
if: ${{matrix.os != 'windows' || matrix.cmake != '3.20'}}
4542
with:
4643
cmake-version: "${{ matrix.cmake }}.x"
4744

48-
- name: Setup cmake (Bump up CMake minimal version for Visual Studio 17 2022)
45+
- name: Setup CMake (Bump up CMake minimal version for Visual Studio 17 2022)
4946
uses: jwlawson/actions-setup-cmake@v2.0
5047
if: ${{matrix.os == 'windows' && matrix.cmake == '3.20'}}
5148
with:
5249
# Visual Studio 17 2022 requires at least CMake 3.21.
5350
# https://cmake.org/cmake/help/latest/generator/Visual%20Studio%2017%202022.html
5451
cmake-version: "3.21.x"
5552

56-
- name: Install nanobind + pytest + pytest-cmake
53+
- name: Setup Environment
5754
shell: bash
5855
run: |
56+
cmake --version
5957
python -m pip install --upgrade pip
6058
python -m pip install nanobind==2.*
6159
python -m pip install . pytest==${{ matrix.pytest }}.*
6260
61+
- name: Build and Run Unit Tests
62+
shell: bash
63+
run: |
64+
cmake -D "CMAKE_BUILD_TYPE=Release" -S ./test -B ./test/build
65+
cmake --build ./test/build
66+
6367
- name: Configure Example
6468
shell: bash
69+
env:
70+
BUNDLE_PYTHON_TESTS: ${{ matrix.bundled }}
6571
run: |
66-
cmake --version
6772
cmake \
6873
-D "CMAKE_BUILD_TYPE=Release" \
6974
-D "nanobind_ROOT=$(python -m nanobind --cmake_dir)" \

test/01-modify-name/CMakeLists.txt

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
3+
project(TestModifyName)
4+
5+
find_package(Pytest 4.6.11 REQUIRED)
6+
7+
enable_testing()
8+
9+
pytest_discover_tests(TestModifyName.Simple)
10+
set(EXPECTED
11+
"TestModifyName.Simple.test_inventory_keys"
12+
"TestModifyName.Simple.test_fruit_quantity[Fruit[banana]=150]"
13+
"TestModifyName.Simple.test_fruit_quantity[Fruit[apple]=100]"
14+
"TestModifyName.Simple.test_inventory_values"
15+
"TestModifyName.Simple.test_fruit_quantity[Fruit[orange]=200]"
16+
"TestModifyName.Simple.TestStringMethods.test_upper"
17+
"TestModifyName.Simple.TestStringMethods.test_lower"
18+
"TestModifyName.Simple.TestStringMethods.test_capitalize"
19+
"TestModifyName.Simple.TestStringMethods.test_split"
20+
"TestModifyName.Simple.test_addition"
21+
"TestModifyName.Simple.test_subtraction"
22+
"TestModifyName.Simple.test_addition_with_params[5-5-10]"
23+
"TestModifyName.Simple.test_addition_with_params[10-5-15]"
24+
"TestModifyName.Simple.test_addition_with_params[0-0-0]"
25+
)
26+
add_test(NAME TestModifyName.Validate.Simple
27+
COMMAND ${CMAKE_COMMAND}
28+
-D "TEST_PREFIX=TestModifyName.Simple"
29+
-D "EXPECTED=${EXPECTED}"
30+
-P ${CMAKE_CURRENT_LIST_DIR}/compare_discovered_tests.cmake
31+
)
32+
33+
pytest_discover_tests(TestModifyName.Bundled BUNDLE_TESTS)
34+
add_test(NAME TestModifyName.Validate.Bundled
35+
COMMAND ${CMAKE_COMMAND}
36+
-D "TEST_PREFIX=TestModifyName.Bundled"
37+
-D "EXPECTED=TestModifyName.Bundled"
38+
-P ${CMAKE_CURRENT_LIST_DIR}/compare_discovered_tests.cmake
39+
)
40+
41+
pytest_discover_tests(
42+
TestModifyName.TrimFromName
43+
TRIM_FROM_NAME "^(Test|test_)"
44+
)
45+
set(EXPECTED
46+
"TestModifyName.TrimFromName.inventory_keys"
47+
"TestModifyName.TrimFromName.inventory_values"
48+
"TestModifyName.TrimFromName.fruit_quantity[Fruit[banana]=150]"
49+
"TestModifyName.TrimFromName.fruit_quantity[Fruit[apple]=100]"
50+
"TestModifyName.TrimFromName.fruit_quantity[Fruit[orange]=200]"
51+
"TestModifyName.TrimFromName.StringMethods.upper"
52+
"TestModifyName.TrimFromName.StringMethods.lower"
53+
"TestModifyName.TrimFromName.StringMethods.capitalize"
54+
"TestModifyName.TrimFromName.StringMethods.split"
55+
"TestModifyName.TrimFromName.addition"
56+
"TestModifyName.TrimFromName.subtraction"
57+
"TestModifyName.TrimFromName.addition_with_params[5-5-10]"
58+
"TestModifyName.TrimFromName.addition_with_params[10-5-15]"
59+
"TestModifyName.TrimFromName.addition_with_params[0-0-0]"
60+
)
61+
add_test(NAME TestModifyName.Validate.TrimFromName
62+
COMMAND ${CMAKE_COMMAND}
63+
-D "TEST_PREFIX=TestModifyName.TrimFromName"
64+
-D "EXPECTED=${EXPECTED}"
65+
-P ${CMAKE_CURRENT_LIST_DIR}/compare_discovered_tests.cmake
66+
)
67+
68+
pytest_discover_tests(
69+
TestModifyName.StripParamBrackets
70+
STRIP_PARAM_BRACKETS
71+
)
72+
set(EXPECTED
73+
"TestModifyName.StripParamBrackets.test_inventory_keys"
74+
"TestModifyName.StripParamBrackets.test_inventory_values"
75+
"TestModifyName.StripParamBrackets.test_fruit_quantity.Fruit[banana]=150"
76+
"TestModifyName.StripParamBrackets.test_fruit_quantity.Fruit[apple]=100"
77+
"TestModifyName.StripParamBrackets.test_fruit_quantity.Fruit[orange]=200"
78+
"TestModifyName.StripParamBrackets.TestStringMethods.test_upper"
79+
"TestModifyName.StripParamBrackets.TestStringMethods.test_lower"
80+
"TestModifyName.StripParamBrackets.TestStringMethods.test_capitalize"
81+
"TestModifyName.StripParamBrackets.TestStringMethods.test_split"
82+
"TestModifyName.StripParamBrackets.test_addition"
83+
"TestModifyName.StripParamBrackets.test_subtraction"
84+
"TestModifyName.StripParamBrackets.test_addition_with_params.5-5-10"
85+
"TestModifyName.StripParamBrackets.test_addition_with_params.10-5-15"
86+
"TestModifyName.StripParamBrackets.test_addition_with_params.0-0-0"
87+
)
88+
add_test(NAME TestModifyName.Validate.StripParamBrackets
89+
COMMAND ${CMAKE_COMMAND}
90+
-D "TEST_PREFIX=TestModifyName.StripParamBrackets"
91+
-D "EXPECTED=${EXPECTED}"
92+
-P ${CMAKE_CURRENT_LIST_DIR}/compare_discovered_tests.cmake
93+
)
94+
95+
pytest_discover_tests(
96+
TestModifyName.IncludeFilePath
97+
INCLUDE_FILE_PATH
98+
)
99+
set(EXPECTED
100+
"TestModifyName.IncludeFilePath.data.test_sample_data.test_inventory_keys"
101+
"TestModifyName.IncludeFilePath.data.test_sample_data.test_inventory_values"
102+
"TestModifyName.IncludeFilePath.data.test_sample_data.test_fruit_quantity[Fruit[banana]=150]"
103+
"TestModifyName.IncludeFilePath.data.test_sample_data.test_fruit_quantity[Fruit[apple]=100]"
104+
"TestModifyName.IncludeFilePath.data.test_sample_data.test_fruit_quantity[Fruit[orange]=200]"
105+
"TestModifyName.IncludeFilePath.strings.test_string_methods.TestStringMethods.test_upper"
106+
"TestModifyName.IncludeFilePath.strings.test_string_methods.TestStringMethods.test_lower"
107+
"TestModifyName.IncludeFilePath.strings.test_string_methods.TestStringMethods.test_capitalize"
108+
"TestModifyName.IncludeFilePath.strings.test_string_methods.TestStringMethods.test_split"
109+
"TestModifyName.IncludeFilePath.test_math_operations.test_addition"
110+
"TestModifyName.IncludeFilePath.test_math_operations.test_subtraction"
111+
"TestModifyName.IncludeFilePath.test_math_operations.test_addition_with_params[5-5-10]"
112+
"TestModifyName.IncludeFilePath.test_math_operations.test_addition_with_params[10-5-15]"
113+
"TestModifyName.IncludeFilePath.test_math_operations.test_addition_with_params[0-0-0]"
114+
)
115+
add_test(NAME TestModifyName.Validate.IncludeFilePath
116+
COMMAND ${CMAKE_COMMAND}
117+
-D "TEST_PREFIX=TestModifyName.IncludeFilePath"
118+
-D "EXPECTED=${EXPECTED}"
119+
-P ${CMAKE_CURRENT_LIST_DIR}/compare_discovered_tests.cmake
120+
)
121+
122+
pytest_discover_tests(
123+
TestModifyName.TrimFromFullName
124+
TRIM_FROM_FULL_NAME "(math_|fruit_|test_)"
125+
INCLUDE_FILE_PATH
126+
)
127+
set(EXPECTED
128+
"TestModifyName.TrimFromFullName.data.sample_data.inventory_keys"
129+
"TestModifyName.TrimFromFullName.data.sample_data.inventory_values"
130+
"TestModifyName.TrimFromFullName.data.sample_data.quantity[Fruit[banana]=150]"
131+
"TestModifyName.TrimFromFullName.data.sample_data.quantity[Fruit[apple]=100]"
132+
"TestModifyName.TrimFromFullName.data.sample_data.quantity[Fruit[orange]=200]"
133+
"TestModifyName.TrimFromFullName.strings.string_methods.TestStringMethods.upper"
134+
"TestModifyName.TrimFromFullName.strings.string_methods.TestStringMethods.lower"
135+
"TestModifyName.TrimFromFullName.strings.string_methods.TestStringMethods.capitalize"
136+
"TestModifyName.TrimFromFullName.strings.string_methods.TestStringMethods.split"
137+
"TestModifyName.TrimFromFullName.operations.addition"
138+
"TestModifyName.TrimFromFullName.operations.subtraction"
139+
"TestModifyName.TrimFromFullName.operations.addition_with_params[5-5-10]"
140+
"TestModifyName.TrimFromFullName.operations.addition_with_params[10-5-15]"
141+
"TestModifyName.TrimFromFullName.operations.addition_with_params[0-0-0]"
142+
)
143+
add_test(NAME TestModifyName.Validate.TrimFromFullName
144+
COMMAND ${CMAKE_COMMAND}
145+
-D "TEST_PREFIX=TestModifyName.TrimFromFullName"
146+
-D "EXPECTED=${EXPECTED}"
147+
-P ${CMAKE_CURRENT_LIST_DIR}/compare_discovered_tests.cmake
148+
)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
3+
execute_process(
4+
COMMAND ${CMAKE_CTEST_COMMAND} --show-only
5+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
6+
OUTPUT_VARIABLE test_output
7+
)
8+
9+
string(REGEX MATCHALL "${TEST_PREFIX}[^\n]*" discovered_tests "${test_output}")
10+
11+
if (NOT discovered_tests)
12+
message(FATAL_ERROR "'${TEST_PREFIX}': No tests discovered.")
13+
endif()
14+
15+
list(SORT discovered_tests)
16+
list(SORT EXPECTED)
17+
18+
string(JOIN ";" discovered_tests_string ${discovered_tests})
19+
string(JOIN ";" expected_tests_string ${EXPECTED})
20+
21+
if(NOT "${discovered_tests_string}" STREQUAL "${expected_tests_string}")
22+
message(FATAL_ERROR
23+
"'${TEST_PREFIX}': The discovered tests list does not match the expected list.\n"
24+
"Expected: ${expected_tests_string}\n"
25+
"Found: ${discovered_tests_string}"
26+
)
27+
endif()
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import pytest
2+
3+
@pytest.fixture
4+
def sample_data():
5+
return {
6+
"banana": {"quantity_in_stock": 150},
7+
"apple": {"quantity_in_stock": 100},
8+
"orange": {"quantity_in_stock": 200}
9+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import pytest
2+
3+
def test_inventory_keys(sample_data):
4+
for fruit in sample_data:
5+
assert "quantity_in_stock" in sample_data[fruit]
6+
7+
def test_inventory_values(sample_data):
8+
for fruit, data in sample_data.items():
9+
assert isinstance(data["quantity_in_stock"], int)
10+
assert data["quantity_in_stock"] > 0
11+
12+
@pytest.mark.parametrize("fruit, expected_quantity", [
13+
("banana", 150),
14+
("apple", 100),
15+
("orange", 200),
16+
], ids=["Fruit[banana]=150", "Fruit[apple]=100", "Fruit[orange]=200"])
17+
def test_fruit_quantity(sample_data, fruit, expected_quantity):
18+
assert sample_data[fruit]["quantity_in_stock"] == expected_quantity
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import pytest
2+
3+
class TestStringMethods:
4+
5+
def test_upper(self):
6+
assert "example".upper() == "EXAMPLE"
7+
8+
def test_lower(self):
9+
assert "EXAMPLE".lower() == "example"
10+
11+
def test_capitalize(self):
12+
assert "hello".capitalize() == "Hello"
13+
14+
def test_split(self):
15+
s = "hello world"
16+
assert s.split() == ["hello", "world"]
17+
with pytest.raises(TypeError):
18+
s.split(2)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import pytest
2+
3+
def test_addition():
4+
assert 2 + 3 == 5
5+
6+
def test_subtraction():
7+
assert 5 - 2 == 3
8+
9+
@pytest.mark.parametrize("a, b, expected", [
10+
(5, 5, 10),
11+
(10, 5, 15),
12+
(0, 0, 0),
13+
])
14+
def test_addition_with_params(a, b, expected):
15+
assert a + b == expected
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
3+
project(TestLibraryPath)
4+
5+
find_package(Pytest 4.6.11 REQUIRED)
6+
7+
enable_testing()
8+
9+
if(WIN32)
10+
set(EXPECTED "\\path")
11+
else()
12+
set(EXPECTED "/path")
13+
endif()
14+
configure_file(test_path.py "test1/test_path.py" @ONLY)
15+
16+
pytest_discover_tests(
17+
TestLibraryPath.AddOne
18+
LIBRARY_PATH_PREPEND "/path"
19+
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test1"
20+
)
21+
22+
if(WIN32)
23+
set(EXPECTED "\\path1;\\path2;\\path3")
24+
else()
25+
set(EXPECTED "/path1:/path2:/path3")
26+
endif()
27+
configure_file(test_path.py "test2/test_path.py" @ONLY)
28+
29+
pytest_discover_tests(
30+
TestLibraryPath.AddSeveral
31+
LIBRARY_PATH_PREPEND "/path1" "/path2" "/path3"
32+
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test2"
33+
)

test/02-library-path/test_path.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import os
2+
import platform
3+
import pytest
4+
5+
PREPENDED_PATH = "@EXPECTED@"
6+
7+
def test_path():
8+
"""Ensure that the path has been prepended as expected."""
9+
env_vars = {
10+
"Linux": "LD_LIBRARY_PATH",
11+
"Darwin": "DYLD_LIBRARY_PATH",
12+
}
13+
env_var = env_vars.get(platform.system(), "PATH")
14+
current_path = os.environ.get(env_var, "")
15+
16+
assert current_path == PREPENDED_PATH or current_path.startswith(PREPENDED_PATH + os.pathsep), \
17+
f"{env_var} does not start with {PREPENDED_PATH}, found: {current_path}"

test/03-python-path/CMakeLists.txt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
3+
project(TestPythonPath)
4+
5+
find_package(Pytest 4.6.11 REQUIRED)
6+
7+
enable_testing()
8+
9+
if(WIN32)
10+
set(EXPECTED "\\path")
11+
else()
12+
set(EXPECTED "/path")
13+
endif()
14+
configure_file(test_path.py "test1/test_path.py" @ONLY)
15+
16+
pytest_discover_tests(
17+
TestPythonPath.AddOne
18+
PYTHON_PATH_PREPEND "/path"
19+
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test1"
20+
)
21+
22+
if(WIN32)
23+
set(EXPECTED "\\path1;\\path2;\\path3")
24+
else()
25+
set(EXPECTED "/path1:/path2:/path3")
26+
endif()
27+
configure_file(test_path.py "test2/test_path.py" @ONLY)
28+
29+
pytest_discover_tests(
30+
TestPythonPath.AddSeveral
31+
PYTHON_PATH_PREPEND "/path1" "/path2" "/path3"
32+
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test2"
33+
)

0 commit comments

Comments
 (0)