Skip to content

Commit 82abdb1

Browse files
committed
[~] tests refaco
1 parent 1373e4c commit 82abdb1

File tree

7 files changed

+129
-58
lines changed

7 files changed

+129
-58
lines changed

.github/workflows/python-package.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
fail-fast: false
1818
matrix:
19-
python-version: ["3.11", "3.12"]
19+
python-version: ["3.12"]
2020

2121
steps:
2222
- uses: actions/checkout@v4
@@ -37,4 +37,4 @@ jobs:
3737
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
3838
- name: Test with pytest
3939
run: |
40-
pytest tests/test_create_totalseg_subset.py
40+
pytest -q

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,11 @@ PSAT addresses pediatric segmentation challenges by combining:
2121
- [Notebooks](notebooks/notebooks.md)
2222
- [Resources](resources/resources.md)
2323
- [Scripts](scripts/scripts.md)
24+
25+
## Running Tests
26+
27+
Install dependencies listed in `requirements.txt` and run:
28+
29+
```bash
30+
pytest -q
31+
```

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ numpy
44
matplotlib
55
nnunetv2
66
scipy
7+
nibabel

scripts/create_dataset_subset.py

Lines changed: 0 additions & 41 deletions
This file was deleted.

tests/test_compute_metrics.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import os
2+
import sys
3+
import types
4+
import numpy as np
5+
import nibabel as nib
6+
7+
# Ensure repo root is on path
8+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
9+
10+
# Dummy modules to satisfy imports in compute_metrics
11+
sys.modules.setdefault('p_tqdm', types.SimpleNamespace(p_map=lambda *a, **k: []))
12+
sys.modules.setdefault('surface_distance', types.SimpleNamespace(
13+
compute_surface_distances=lambda *a, **k: None,
14+
compute_robust_hausdorff=lambda *a, **k: 0,
15+
))
16+
17+
from scripts.compute_metrics import dice_score, calculate_confidence_interval, reorient_to_ras
18+
19+
20+
def test_dice_score_perfect_match():
21+
y_true = np.array([[1, 0], [0, 1]])
22+
y_pred = np.array([[1, 0], [0, 1]])
23+
assert np.isclose(dice_score(y_true, y_pred), 1)
24+
25+
26+
def test_dice_score_partial():
27+
y_true = np.array([[1, 1], [0, 0]])
28+
y_pred = np.array([[1, 0], [1, 0]])
29+
assert np.isclose(dice_score(y_true, y_pred), 0.5)
30+
31+
32+
def test_confidence_interval():
33+
data = [1, 1, 1, 1]
34+
mean, lower, upper = calculate_confidence_interval(data, confidence=0.95)
35+
assert mean == 1
36+
assert lower <= mean <= upper
37+
38+
39+
def test_reorient_to_ras_identity():
40+
arr = np.zeros((2, 2, 2))
41+
affine = np.eye(4)
42+
img = nib.Nifti1Image(arr, affine)
43+
ras_img = reorient_to_ras(img)
44+
assert ras_img.get_fdata().shape == img.get_fdata().shape
Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,60 @@
11
# FILE: tests/test_create_totalseg_subset.py
2-
import unittest
3-
import pandas as pd
42
import os
5-
from scripts.create_totalseg_subset import plot_and_save_distribution
3+
import sys
4+
import pandas as pd
5+
import pytest
6+
7+
# Ensure package import works when tests are run directly
8+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
9+
10+
from scripts.create_totalseg_subset import plot_and_save_distribution, create_directory_structure, copy_selected_files
611

7-
class TestCreateTotalSegSubset(unittest.TestCase):
8-
def setUp(self):
12+
class TestCreateTotalSegSubset:
13+
@pytest.fixture(autouse=True)
14+
def setup_and_teardown(self, tmp_path):
915
# Create a sample dataframe
1016
self.data = pd.DataFrame({
1117
'age': [25, 35, 45, 55, 65, 75],
1218
'gender': ['M', 'F', 'M', 'F', 'M', 'F']
1319
})
14-
self.filename = 'test_distribution.png'
20+
self.filename = tmp_path / 'test_distribution.png'
21+
yield
22+
# Remove the file after test if it exists
23+
if self.filename.exists():
24+
self.filename.unlink()
1525

1626
def test_plot_and_save_distribution(self):
1727
# Call the function to plot and save the distribution
18-
plot_and_save_distribution(self.data, "Test Title", self.filename)
19-
28+
plot_and_save_distribution(self.data, "Test Title", str(self.filename))
2029
# Check if the file is created
21-
self.assertTrue(os.path.exists(self.filename))
30+
assert self.filename.exists()
2231

23-
def tearDown(self):
24-
# Remove the file after test
25-
if os.path.exists(self.filename):
26-
os.remove(self.filename)
32+
def test_create_directory_structure(self, tmp_path):
33+
subdirs = ["imagesTr", "labelsTr"]
34+
create_directory_structure(tmp_path, subdirs)
35+
for subdir in subdirs:
36+
assert (tmp_path / subdir).exists()
37+
assert (tmp_path / subdir).is_dir()
2738

28-
if __name__ == '__main__':
29-
unittest.main()
39+
def test_copy_selected_files(self, tmp_path):
40+
# Setup original and new base directories
41+
original_base = tmp_path / "original"
42+
new_base = tmp_path / "new"
43+
subdirs = ["imagesTr", "labelsTr"]
44+
image_ids = ["img001", "img002"]
45+
create_directory_structure(original_base, subdirs)
46+
create_directory_structure(new_base, subdirs)
47+
# Create files in original_base
48+
for subdir in subdirs:
49+
for img_id in image_ids:
50+
file_path = original_base / subdir / f"{img_id}_something.nii.gz"
51+
file_path.write_text("dummy data")
52+
# Add a file that should not be copied
53+
(original_base / subdir / "otherfile.nii.gz").write_text("not copied")
54+
# Copy selected files
55+
copy_selected_files(original_base, new_base, subdirs, image_ids)
56+
# Check that only the correct files are copied
57+
for subdir in subdirs:
58+
for img_id in image_ids:
59+
assert (new_base / subdir / f"{img_id}_something.nii.gz").exists()
60+
assert not (new_base / subdir / "otherfile.nii.gz").exists()

tests/test_get_results.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import os
2+
import sys
3+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
4+
5+
from scripts.get_results import escape_latex, is_baseline, compute_statistical_tests, determine_best_scores
6+
import numpy as np
7+
8+
9+
def test_escape_latex():
10+
assert escape_latex('foo_bar') == 'foo\\_bar'
11+
12+
13+
def test_is_baseline():
14+
assert is_baseline('Something_TotalSegmentator')
15+
assert not is_baseline('OtherModel')
16+
17+
18+
def test_compute_statistical_tests_and_best_scores():
19+
results = {
20+
'Baseline_TotalSegmentator': {'ROI': {'dataset': {'dice': [0.8, 0.9]}}},
21+
'NewModel': {'ROI': {'dataset': {'dice': [0.95, 0.96]}}},
22+
}
23+
compute_statistical_tests(results)
24+
assert 'pvalue' in results['NewModel']['ROI']['dataset']
25+
assert 'max_baseline' in results['NewModel']['ROI']['dataset']
26+
27+
best = determine_best_scores(results, ['dataset'], ['Baseline_TotalSegmentator', 'NewModel'], ['ROI'])
28+
assert best['ROI']['dataset'] == 'NewModel'

0 commit comments

Comments
 (0)