-
Notifications
You must be signed in to change notification settings - Fork 163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tests for birdnet_analyzer.analyze
module
#527
base: main
Are you sure you want to change the base?
Changes from all commits
99a7d5a
49dd20b
a6100c1
13e339f
8703779
a3a100b
0eece4a
5035c9b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Selection View Channel Begin Time (s) End Time (s) Low Freq (Hz) High Freq (Hz) Common Name Species Code Confidence Begin Path File Offset (s) | ||
1 Spectrogram 1 1 0 3.0 0 15000 Black-capped Chickadee bkcchi 0.8141 birdnet_analyzer/example/soundscape.wav 0 | ||
2 Spectrogram 1 1 9.0 12.0 0 15000 House Finch houfin 0.6394 birdnet_analyzer/example/soundscape.wav 9.0 | ||
3 Spectrogram 1 1 42.0 45.0 0 15000 Dark-eyed Junco daejun 0.7375 birdnet_analyzer/example/soundscape.wav 42.0 | ||
4 Spectrogram 1 1 54.0 57.0 0 15000 House Finch houfin 0.6071 birdnet_analyzer/example/soundscape.wav 54.0 | ||
5 Spectrogram 1 1 60.0 63.0 0 15000 Dark-eyed Junco daejun 0.5550 birdnet_analyzer/example/soundscape.wav 60.0 | ||
6 Spectrogram 1 1 72.0 75.0 0 15000 House Finch houfin 0.5638 birdnet_analyzer/example/soundscape.wav 72.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
Selection View Channel Begin Time (s) End Time (s) Low Freq (Hz) High Freq (Hz) Common Name Species Code Confidence Begin Path File Offset (s) | ||
1 Spectrogram 1 1 0 3.0 0 15000 Black-capped Chickadee bkcchi 0.8141 birdnet_analyzer/example/soundscape.wav 0 | ||
2 Spectrogram 1 1 3.0 6.0 0 15000 Black-capped Chickadee bkcchi 0.3083 birdnet_analyzer/example/soundscape.wav 3.0 | ||
3 Spectrogram 1 1 6.0 9.0 0 15000 Tufted Titmouse tuftit 0.1864 birdnet_analyzer/example/soundscape.wav 6.0 | ||
4 Spectrogram 1 1 9.0 12.0 0 15000 House Finch houfin 0.6394 birdnet_analyzer/example/soundscape.wav 9.0 | ||
5 Spectrogram 1 1 18.0 21.0 0 15000 Blue Jay blujay 0.4353 birdnet_analyzer/example/soundscape.wav 18.0 | ||
6 Spectrogram 1 1 21.0 24.0 0 15000 Blue Jay blujay 0.3291 birdnet_analyzer/example/soundscape.wav 21.0 | ||
7 Spectrogram 1 1 21.0 24.0 0 15000 House Finch houfin 0.1867 birdnet_analyzer/example/soundscape.wav 21.0 | ||
8 Spectrogram 1 1 24.0 27.0 0 15000 Blue Jay blujay 0.1749 birdnet_analyzer/example/soundscape.wav 24.0 | ||
9 Spectrogram 1 1 27.0 30.0 0 15000 Dark-eyed Junco daejun 0.2187 birdnet_analyzer/example/soundscape.wav 27.0 | ||
10 Spectrogram 1 1 33.0 36.0 0 15000 Dark-eyed Junco daejun 0.4591 birdnet_analyzer/example/soundscape.wav 33.0 | ||
11 Spectrogram 1 1 36.0 39.0 0 15000 Dark-eyed Junco daejun 0.3537 birdnet_analyzer/example/soundscape.wav 36.0 | ||
12 Spectrogram 1 1 39.0 42.0 0 15000 House Finch houfin 0.2533 birdnet_analyzer/example/soundscape.wav 39.0 | ||
13 Spectrogram 1 1 42.0 45.0 0 15000 Dark-eyed Junco daejun 0.7375 birdnet_analyzer/example/soundscape.wav 42.0 | ||
14 Spectrogram 1 1 48.0 51.0 0 15000 Blue Jay blujay 0.1293 birdnet_analyzer/example/soundscape.wav 48.0 | ||
15 Spectrogram 1 1 51.0 54.0 0 15000 House Finch houfin 0.2564 birdnet_analyzer/example/soundscape.wav 51.0 | ||
16 Spectrogram 1 1 54.0 57.0 0 15000 House Finch houfin 0.6071 birdnet_analyzer/example/soundscape.wav 54.0 | ||
17 Spectrogram 1 1 57.0 60.0 0 15000 House Finch houfin 0.1615 birdnet_analyzer/example/soundscape.wav 57.0 | ||
18 Spectrogram 1 1 60.0 63.0 0 15000 Dark-eyed Junco daejun 0.5550 birdnet_analyzer/example/soundscape.wav 60.0 | ||
19 Spectrogram 1 1 69.0 72.0 0 15000 House Finch houfin 0.2915 birdnet_analyzer/example/soundscape.wav 69.0 | ||
20 Spectrogram 1 1 72.0 75.0 0 15000 House Finch houfin 0.5638 birdnet_analyzer/example/soundscape.wav 72.0 | ||
21 Spectrogram 1 1 78.0 81.0 0 15000 House Finch houfin 0.2561 birdnet_analyzer/example/soundscape.wav 78.0 | ||
22 Spectrogram 1 1 84.0 87.0 0 15000 House Finch houfin 0.2801 birdnet_analyzer/example/soundscape.wav 84.0 | ||
23 Spectrogram 1 1 90.0 93.0 0 15000 American Goldfinch amegfi 0.4190 birdnet_analyzer/example/soundscape.wav 90.0 | ||
24 Spectrogram 1 1 93.0 96.0 0 15000 House Finch houfin 0.3168 birdnet_analyzer/example/soundscape.wav 93.0 | ||
25 Spectrogram 1 1 96.0 99.0 0 15000 American Goldfinch amegfi 0.4765 birdnet_analyzer/example/soundscape.wav 96.0 | ||
26 Spectrogram 1 1 99.0 102.0 0 15000 House Finch houfin 0.1574 birdnet_analyzer/example/soundscape.wav 99.0 | ||
27 Spectrogram 1 1 102.0 105.0 0 15000 House Finch houfin 0.4459 birdnet_analyzer/example/soundscape.wav 102.0 | ||
28 Spectrogram 1 1 105.0 108.0 0 15000 Black-capped Chickadee bkcchi 0.1790 birdnet_analyzer/example/soundscape.wav 105.0 | ||
29 Spectrogram 1 1 117.0 120.0 0 15000 American Goldfinch amegfi 0.3924 birdnet_analyzer/example/soundscape.wav 117.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
Selection View Channel Begin Time (s) End Time (s) Low Freq (Hz) High Freq (Hz) Common Name Species Code Confidence Begin Path File Offset (s) | ||
1 Spectrogram 1 1 0 3.0 0 15000 Schwarzkopfmeise bkcchi 0.8141 birdnet_analyzer/example/soundscape.wav 0 | ||
2 Spectrogram 1 1 3.0 6.0 0 15000 Schwarzkopfmeise bkcchi 0.3083 birdnet_analyzer/example/soundscape.wav 3.0 | ||
3 Spectrogram 1 1 6.0 9.0 0 15000 Grauhäubchenmeise tuftit 0.1864 birdnet_analyzer/example/soundscape.wav 6.0 | ||
4 Spectrogram 1 1 9.0 12.0 0 15000 Hausgimpel houfin 0.6394 birdnet_analyzer/example/soundscape.wav 9.0 | ||
5 Spectrogram 1 1 18.0 21.0 0 15000 Blauhäher blujay 0.4353 birdnet_analyzer/example/soundscape.wav 18.0 | ||
6 Spectrogram 1 1 21.0 24.0 0 15000 Blauhäher blujay 0.3291 birdnet_analyzer/example/soundscape.wav 21.0 | ||
7 Spectrogram 1 1 21.0 24.0 0 15000 Hausgimpel houfin 0.1867 birdnet_analyzer/example/soundscape.wav 21.0 | ||
8 Spectrogram 1 1 24.0 27.0 0 15000 Blauhäher blujay 0.1749 birdnet_analyzer/example/soundscape.wav 24.0 | ||
9 Spectrogram 1 1 27.0 30.0 0 15000 Winterammer daejun 0.2187 birdnet_analyzer/example/soundscape.wav 27.0 | ||
10 Spectrogram 1 1 33.0 36.0 0 15000 Winterammer daejun 0.4591 birdnet_analyzer/example/soundscape.wav 33.0 | ||
11 Spectrogram 1 1 36.0 39.0 0 15000 Winterammer daejun 0.3537 birdnet_analyzer/example/soundscape.wav 36.0 | ||
12 Spectrogram 1 1 39.0 42.0 0 15000 Hausgimpel houfin 0.2533 birdnet_analyzer/example/soundscape.wav 39.0 | ||
13 Spectrogram 1 1 42.0 45.0 0 15000 Winterammer daejun 0.7375 birdnet_analyzer/example/soundscape.wav 42.0 | ||
14 Spectrogram 1 1 48.0 51.0 0 15000 Blauhäher blujay 0.1293 birdnet_analyzer/example/soundscape.wav 48.0 | ||
15 Spectrogram 1 1 51.0 54.0 0 15000 Hausgimpel houfin 0.2564 birdnet_analyzer/example/soundscape.wav 51.0 | ||
16 Spectrogram 1 1 54.0 57.0 0 15000 Hausgimpel houfin 0.6071 birdnet_analyzer/example/soundscape.wav 54.0 | ||
17 Spectrogram 1 1 57.0 60.0 0 15000 Hausgimpel houfin 0.1615 birdnet_analyzer/example/soundscape.wav 57.0 | ||
18 Spectrogram 1 1 60.0 63.0 0 15000 Winterammer daejun 0.5550 birdnet_analyzer/example/soundscape.wav 60.0 | ||
19 Spectrogram 1 1 69.0 72.0 0 15000 Hausgimpel houfin 0.2915 birdnet_analyzer/example/soundscape.wav 69.0 | ||
20 Spectrogram 1 1 72.0 75.0 0 15000 Hausgimpel houfin 0.5638 birdnet_analyzer/example/soundscape.wav 72.0 | ||
21 Spectrogram 1 1 78.0 81.0 0 15000 Hausgimpel houfin 0.2561 birdnet_analyzer/example/soundscape.wav 78.0 | ||
22 Spectrogram 1 1 84.0 87.0 0 15000 Hausgimpel houfin 0.2801 birdnet_analyzer/example/soundscape.wav 84.0 | ||
23 Spectrogram 1 1 90.0 93.0 0 15000 Goldzeisig amegfi 0.4190 birdnet_analyzer/example/soundscape.wav 90.0 | ||
24 Spectrogram 1 1 93.0 96.0 0 15000 Hausgimpel houfin 0.3168 birdnet_analyzer/example/soundscape.wav 93.0 | ||
25 Spectrogram 1 1 96.0 99.0 0 15000 Goldzeisig amegfi 0.4765 birdnet_analyzer/example/soundscape.wav 96.0 | ||
26 Spectrogram 1 1 99.0 102.0 0 15000 Hausgimpel houfin 0.1574 birdnet_analyzer/example/soundscape.wav 99.0 | ||
27 Spectrogram 1 1 102.0 105.0 0 15000 Hausgimpel houfin 0.4459 birdnet_analyzer/example/soundscape.wav 102.0 | ||
28 Spectrogram 1 1 105.0 108.0 0 15000 Schwarzkopfmeise bkcchi 0.1790 birdnet_analyzer/example/soundscape.wav 105.0 | ||
29 Spectrogram 1 1 117.0 120.0 0 15000 Goldzeisig amegfi 0.3924 birdnet_analyzer/example/soundscape.wav 117.0 |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added postfix Reason: If unit tests are eventually added, it will help with the organization, since e2e tests usually take more time to run (seconds instead of milliseconds) & aren’t very precise about “what is broken” compared to unit tests, so it’s good to know which is which. I find there is inevitably a desire to separate them. Happy to suggest a rename to |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# tests/test_analyze__main.py | ||
# | ||
# These are end-to-end tests that run module `birdnet_analyzer.analyze` | ||
# as if calling it from the command-line. | ||
# | ||
# When run with certain arguments on known example input, | ||
# an output file should be generated with expected specific format and data | ||
# as found in tests/resources/SNAPSHOT.analyze__main.*) | ||
# | ||
# How to run these tests; | ||
# 1. (Prerequisite) from root of this repository, in your virtual environment run: | ||
# ``` | ||
# pip install -r requirements.txt | ||
# ``` | ||
# 2. From root of this repository run: `pytest tests/test_analyze__main.py` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I originally started adding a If you, the maintainers of this project, like having these and/or other kinds of tests, I’d be happy to help to add more of them and provide usable documentation in other PRs, as preferred. Happy also to add a simple github action PR to run such tests automatically, e.g. when someone opens a PR these could do a baseline check for regression in advance of your review. |
||
|
||
import subprocess | ||
import os | ||
|
||
def test_analyze_case1_example_min_conf(tmp_path): | ||
""" | ||
Tests a command similar to: | ||
python3 analyze.py --i example/ --o example/ --slist example/ --min_conf 0.5 --threads 4 | ||
""" | ||
# GIVEN: analyze is called on example/ dir with 1 sound file, soundscape.wav, with a minimum confidence level of 0.5 | ||
output_dir = tmp_path | ||
# comment the following line in in order to write a file to troubleshoot or take a new snapshot | ||
# output_dir = 'birdnet_analyzer/example' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment is added, because this code intentionally uses As well, an appropriate time to change the SNAPSHOTs themselves would be when a new model is introduced, so specific values like |
||
cmd = [ | ||
'python', | ||
'-m','birdnet_analyzer.analyze', | ||
'--i', 'birdnet_analyzer/example/', | ||
'--o', output_dir, | ||
'--slist', 'example/', | ||
'--min_conf', '0.5', | ||
'--threads', '4' | ||
] | ||
|
||
# WHEN: analyze is run | ||
result = subprocess.run(cmd, capture_output=True, text=True) | ||
|
||
# THEN: the file created by analyze matches the expected SNAPSHOT (e.g. with fewer results than default confidence threshold) | ||
SNAPSHOT_FILE_OF_EXPECTED='tests/resources/SNAPSHOT.analyze__main.case1.expected.table.txt' | ||
output_file = f'{output_dir}/soundscape.BirdNET.selection.table.txt' | ||
assert result.returncode == 0, f"Command failed with error: {result.stderr}" | ||
assert os.path.exists(output_file), f"File should exist but doesn't: {output_file}" | ||
with open(output_file, 'r') as f1, open(SNAPSHOT_FILE_OF_EXPECTED, 'r') as f2: | ||
assert f1.read() == f2.read() | ||
|
||
|
||
def test_analyze_case2_soundscape(tmp_path): | ||
""" | ||
Tests a command similar to: | ||
python3 analyze.py --i example/soundscape.wav --o example/soundscape.BirdNET.selection.table.txt --slist example/species_list.txt --threads 8 | ||
""" | ||
|
||
# GIVEN: analyze is called on single file: soundscape.wav | ||
output_dir = tmp_path | ||
# comment the following line in in order to write a file to troubleshoot or take a new snapshot | ||
# output_dir = 'birdnet_analyzer/example' | ||
cmd = [ | ||
'python', | ||
'-m','birdnet_analyzer.analyze', | ||
'--i', 'birdnet_analyzer/example/soundscape.wav', | ||
'--o', output_dir, | ||
'--slist', 'example/species_list.txt', | ||
'--threads', '8' | ||
] | ||
|
||
# WHEN: analyze is run | ||
result = subprocess.run(cmd, capture_output=True, text=True) | ||
|
||
# THEN: the file created by analyze matches the expected SNAPSHOT | ||
SNAPSHOT_FILE_OF_EXPECTED='tests/resources/SNAPSHOT.analyze__main.case2.expected.table.txt' | ||
output_file = f'{output_dir}/soundscape.BirdNET.selection.table.txt' | ||
assert result.returncode == 0, f"Command failed with error: {result.stderr}" | ||
assert os.path.exists(output_file), f"File should exist but doesn't: {output_file}" | ||
with open(output_file, 'r') as f1, open(SNAPSHOT_FILE_OF_EXPECTED, 'r') as f2: | ||
assert f1.read() == f2.read() | ||
|
||
|
||
def test_analyze_case3_latlon_week4_sensitivity_rtype_de(tmp_path): | ||
""" | ||
Tests a command similar to: | ||
python3 analyze.py --i example/ --o example/ --lat 42.5 --lon -76.45 --week 4 --sensitivity 1.0 --rtype table --locale de | ||
""" | ||
|
||
# GIVEN: analyze is called on with lat, lon, week, sensitivity, rtype, and locale set | ||
output_dir = tmp_path | ||
# comment the following line in in order to write a file to troubleshoot or take a new snapshot | ||
# output_dir = 'birdnet_analyzer/example' | ||
cmd = [ | ||
'python', | ||
'-m','birdnet_analyzer.analyze', | ||
'--i', 'birdnet_analyzer/example/', | ||
'--o', output_dir, | ||
'--slist', 'example/', | ||
'--lat', '42.5', | ||
'--lon', '-76.45', | ||
'--week', '4', | ||
'--sensitivity', '1.0', | ||
'--rtype', 'table', | ||
'--locale', 'de' | ||
] | ||
|
||
# WHEN: analyze is run | ||
result = subprocess.run(cmd, capture_output=True, text=True) | ||
|
||
# THEN: the file created by analyze matches the expected SNAPSHOT (e.g. in German with expected data) | ||
SNAPSHOT_FILE_OF_EXPECTED='tests/resources/SNAPSHOT.analyze__main.case3.expected.table.txt' | ||
output_file = f'{output_dir}/soundscape.BirdNET.selection.table.txt' | ||
assert result.returncode == 0, f"Command failed with error: {result.stderr}" | ||
assert os.path.exists(output_file), f"File should exist but doesn't: {output_file}" | ||
with open(output_file, 'r') as f1, open(SNAPSHOT_FILE_OF_EXPECTED, 'r') as f2: | ||
assert f1.read() == f2.read() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally added this as
requirements-dev.txt
, but then thought to keep-it-simple by leaving it here