Skip to content

Commit d272e4a

Browse files
committed
Added integration test covering real execution with all model architectures
1 parent af25ca8 commit d272e4a

File tree

7 files changed

+188
-37
lines changed

7 files changed

+188
-37
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: run-integration-tests
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
integration-test:
9+
runs-on: macos-latest-xlarge
10+
env:
11+
AUDIO_SEPARATOR_MODEL_DIR: ${{ github.workspace }}/models
12+
13+
steps:
14+
- name: Checkout project
15+
uses: actions/checkout@v4
16+
17+
- name: Install poetry
18+
run: pipx install poetry
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: '3.13'
24+
cache: poetry
25+
26+
- name: Create models directory
27+
run: mkdir -p $AUDIO_SEPARATOR_MODEL_DIR
28+
29+
- name: Cache models directory
30+
uses: actions/cache@v3
31+
id: model-cache
32+
with:
33+
path: ${{ env.AUDIO_SEPARATOR_MODEL_DIR }}
34+
key: model-cache-${{ hashFiles('tests/integration/test_cli_integration.py') }}
35+
restore-keys: model-cache-
36+
37+
- name: Install Poetry dependencies (CPU covers M1)
38+
run: poetry install -E cpu
39+
40+
- name: Display model cache status
41+
run: |
42+
echo "Model cache hit: ${{ steps.model-cache.outputs.cache-hit == 'true' }}"
43+
echo "Models directory contents:"
44+
ls -la $AUDIO_SEPARATOR_MODEL_DIR || echo "Directory empty or doesn't exist"
45+
46+
- name: Run integration tests
47+
run: poetry run pytest tests -v --cov=audio_separator --cov-report=xml
48+
49+
- name: Upload coverage reports to Codecov
50+
uses: codecov/codecov-action@v3
51+
env:
52+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
53+
54+
- name: Upload test results
55+
if: always()
56+
uses: actions/upload-artifact@v3
57+
with:
58+
name: integration-test-results
59+
path: |
60+
*.flac
61+
tests/*.flac
Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: run-tests
1+
name: run-unit-tests
22

33
on:
44
push:
@@ -29,12 +29,7 @@ jobs:
2929
run: poetry install -E cpu
3030

3131
- name: Run unit tests with coverage
32-
run: poetry run pytest tests/unit --cov=./ --cov-report=xml
33-
34-
- name: Upload coverage reports to Codecov
35-
uses: codecov/codecov-action@v3
36-
env:
37-
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
32+
run: poetry run pytest tests/unit
3833

3934
test-macos:
4035
runs-on: macos-latest
@@ -61,12 +56,7 @@ jobs:
6156

6257
- name: Run unit tests with coverage
6358
run: |
64-
poetry run pytest tests/unit --cov=./ --cov-report=xml
65-
66-
- name: Upload coverage reports to Codecov
67-
uses: codecov/codecov-action@v3
68-
env:
69-
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
59+
poetry run pytest tests/unit
7060
7161
test-windows:
7262
runs-on: windows-latest
@@ -92,9 +82,4 @@ jobs:
9282
run: poetry install -E cpu
9383

9484
- name: Run unit tests with coverage
95-
run: poetry run pytest tests/unit --cov=./ --cov-report=xml
96-
97-
- name: Upload coverage reports to Codecov
98-
uses: codecov/codecov-action@v3
99-
env:
100-
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
85+
run: poetry run pytest tests/unit

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*.onnx
1010
*.pth
1111
*.wav
12-
*.flac
12+
/*.flac
1313
*.mp3
1414
tests/model-metrics/results
1515
tests/model-metrics/datasets

tests/inputs/mardy20s.flac

2.36 MB
Binary file not shown.

tests/integration/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Integration Tests
2+
3+
These tests verify the end-to-end functionality of the audio-separator CLI.
4+
5+
## Running the tests
6+
7+
To run the integration tests, use:
8+
9+
```bash
10+
pytest tests/integration
11+
```
12+
13+
To run a specific model test, you can use pytest's parameter selection:
14+
15+
```bash
16+
# Run only the kuielab_b_vocals.onnx test
17+
pytest tests/integration/test_cli_integration.py::test_model_separation[kuielab_b_vocals.onnx-expected_files0]
18+
19+
# Run only the MGM_MAIN_v4.pth test
20+
pytest tests/integration/test_cli_integration.py::test_model_separation[MGM_MAIN_v4.pth-expected_files1]
21+
```
22+
23+
## Adding New Model Tests
24+
25+
To add a new model test, simply add a new entry to the `MODEL_PARAMS` list in the test file:
26+
27+
```python
28+
(
29+
"new_model_filename.onnx",
30+
["mardy20s_(Instrumental)_new_model_filename.flac", "mardy20s_(Vocals)_new_model_filename.flac"]
31+
),
32+
```
33+
34+
No additional test functions are needed.
35+
36+
## Notes
37+
38+
- These tests use actual audio files and models, and will run the full audio separation process.
39+
- Tests may take longer to run than unit tests, as they perform actual audio processing.
40+
- The model files will be automatically downloaded if they don't exist locally.
41+
- The test requires the test audio file at `tests/inputs/mardy20s.flac` to exist.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import os
2+
import subprocess
3+
import pytest
4+
5+
6+
@pytest.fixture(name="input_file")
7+
def fixture_input_file():
8+
"""Fixture providing the test input audio file path."""
9+
return "tests/inputs/mardy20s.flac"
10+
11+
12+
@pytest.fixture(name="cleanup_output_files")
13+
def fixture_cleanup_output_files():
14+
"""Fixture to clean up output files before and after test."""
15+
# This list will be populated by the test functions
16+
output_files = []
17+
18+
# Yield to allow the test to run and add files to the list
19+
yield output_files
20+
21+
# Clean up output files after test
22+
for file in output_files:
23+
if os.path.exists(file):
24+
print(f"Test output file exists: {file}")
25+
# os.remove(file)
26+
27+
28+
def run_separation_test(model, audio_path, expected_files):
29+
"""Helper function to run a separation test with a specific model."""
30+
# Clean up any existing output files before the test
31+
for file in expected_files:
32+
if os.path.exists(file):
33+
print(f"Deleting existing test output file {file}")
34+
os.remove(file)
35+
36+
# Run the CLI command
37+
result = subprocess.run(["audio-separator", "-m", model, audio_path], capture_output=True, text=True, check=False) # Explicitly set check to False as we handle errors manually
38+
39+
# Check that the command completed successfully
40+
assert result.returncode == 0, f"Command failed with output: {result.stderr}"
41+
42+
# Check that the output files were created
43+
for file in expected_files:
44+
assert os.path.exists(file), f"Output file {file} was not created"
45+
assert os.path.getsize(file) > 0, f"Output file {file} is empty"
46+
47+
return result
48+
49+
50+
# Parameterized test for multiple models
51+
MODEL_PARAMS = [
52+
# (model_filename, expected_output_filenames)
53+
("kuielab_b_vocals.onnx", ["mardy20s_(Instrumental)_kuielab_b_vocals.flac", "mardy20s_(Vocals)_kuielab_b_vocals.flac"]),
54+
("MGM_MAIN_v4.pth", ["mardy20s_(Instrumental)_MGM_MAIN_v4.flac", "mardy20s_(Vocals)_MGM_MAIN_v4.flac"]),
55+
("UVR-MDX-NET-Inst_HQ_4.onnx", ["mardy20s_(Instrumental)_UVR-MDX-NET-Inst_HQ_4.flac", "mardy20s_(Vocals)_UVR-MDX-NET-Inst_HQ_4.flac"]),
56+
("2_HP-UVR.pth", ["mardy20s_(Instrumental)_2_HP-UVR.flac", "mardy20s_(Vocals)_2_HP-UVR.flac"]),
57+
(
58+
"htdemucs_6s.yaml",
59+
[
60+
"mardy20s_(Vocals)_htdemucs_6s.flac",
61+
"mardy20s_(Drums)_htdemucs_6s.flac",
62+
"mardy20s_(Bass)_htdemucs_6s.flac",
63+
"mardy20s_(Other)_htdemucs_6s.flac",
64+
"mardy20s_(Guitar)_htdemucs_6s.flac",
65+
"mardy20s_(Piano)_htdemucs_6s.flac",
66+
],
67+
),
68+
("model_bs_roformer_ep_937_sdr_10.5309.ckpt", ["mardy20s_(Drum-Bass)_model_bs_roformer_ep_937_sdr_10.flac", "mardy20s_(No Drum-Bass)_model_bs_roformer_ep_937_sdr_10.flac"]),
69+
("model_bs_roformer_ep_317_sdr_12.9755.ckpt", ["mardy20s_(Instrumental)_model_bs_roformer_ep_317_sdr_12.flac", "mardy20s_(Vocals)_model_bs_roformer_ep_317_sdr_12.flac"]),
70+
]
71+
72+
73+
@pytest.mark.parametrize("model,expected_files", MODEL_PARAMS)
74+
def test_model_separation(model, expected_files, input_file, cleanup_output_files):
75+
"""Parameterized test for multiple model files."""
76+
# Add files to the cleanup list
77+
cleanup_output_files.extend(expected_files)
78+
79+
# Run the test
80+
run_separation_test(model, input_file, expected_files)

tests/unit/test_cli.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -240,23 +240,7 @@ def test_cli_use_autocast_argument(common_expected_args):
240240
expected_args["use_autocast"] = True
241241

242242
# Assertions
243-
mock_separator.assert_called_once_with(**common_expected_args)
244-
245-
246-
# Test using use_autocast argument
247-
def test_cli_use_autocast_argument(common_expected_args):
248-
test_args = ["cli.py", "test_audio.mp3", "--use_autocast"]
249-
with patch("sys.argv", test_args):
250-
with patch("audio_separator.separator.Separator") as mock_separator:
251-
mock_separator_instance = mock_separator.return_value
252-
mock_separator_instance.separate.return_value = ["output_file.mp3"]
253-
main()
254-
255-
# Update expected args for this specific test
256-
common_expected_args["use_autocast"] = True
257-
258-
# Assertions
259-
mock_separator.assert_called_once_with(**common_expected_args)
243+
mock_separator.assert_called_once_with(**expected_args)
260244

261245

262246
# Test using custom_output_names argument

0 commit comments

Comments
 (0)