137 lines
4.6 KiB
Python
137 lines
4.6 KiB
Python
"""
|
|
Tests for miscellaneous utility functions found in utils/misc.py.
|
|
"""
|
|
import bootstrap # noqa: F401
|
|
import pytest
|
|
|
|
# Import the functions to be tested
|
|
from nodes.utils.misc import parse_note_to_frequency, parse_time_to_seconds
|
|
|
|
|
|
# --- Test Cases for parse_time_to_seconds ---
|
|
|
|
# Use pytest.mark.parametrize to test many valid inputs efficiently
|
|
@pytest.mark.parametrize("time_str, expected_seconds", [
|
|
# Basic cases
|
|
("10", 10.0),
|
|
("15.5", 15.5),
|
|
("0", 0.0),
|
|
|
|
# MM:SS format
|
|
("1:30", 90.0),
|
|
("01:30", 90.0),
|
|
("00:45", 45.0),
|
|
("10:00", 600.0),
|
|
|
|
# MM:SS.ss format
|
|
("1:30.5", 90.5),
|
|
("0:05.25", 5.25),
|
|
|
|
# HH:MM:SS format
|
|
("1:00:00", 3600.0),
|
|
("01:00:00", 3600.0),
|
|
("0:10:20", 620.0),
|
|
|
|
# HH:MM:SS.ss format
|
|
("1:01:01.5", 3661.5),
|
|
("00:00:00.123", 0.123),
|
|
|
|
# Edge cases
|
|
("", 0.0), # Empty string should default to 0
|
|
(" 30.5 ", 30.5), # Should handle whitespace
|
|
(None, 0.0), # None should default to 0
|
|
])
|
|
def test_parse_time_valid_inputs(time_str, expected_seconds):
|
|
"""Tests various valid time string formats."""
|
|
assert parse_time_to_seconds(time_str) == pytest.approx(expected_seconds)
|
|
|
|
|
|
# Use pytest.mark.parametrize for invalid inputs that should raise ValueError
|
|
@pytest.mark.parametrize("invalid_time_str, expected_error_msg_part", [
|
|
# Invalid characters
|
|
("abc", "Invalid time format"),
|
|
("10s", "Invalid time format"),
|
|
("1:20s", "Invalid time format"),
|
|
|
|
# Malformed structures
|
|
("1:2:3:4", "Invalid time format"), # Too many colons
|
|
("1::30", "Empty part in time string"), # Empty part
|
|
(":", "Empty part in time string"),
|
|
(":30", "Empty part in time string"),
|
|
|
|
# Invalid numbers within segments
|
|
("1:70", "Minutes or seconds segment is out of range (0-59)"), # Seconds > 59
|
|
("1:60", "Minutes or seconds segment is out of range (0-59)"), # Seconds == 60
|
|
("70:30", "Minutes or seconds segment is out of range (0-59)"), # Minutes > 59
|
|
("1:30:80", "Minutes or seconds segment is out of range (0-59)"), # Seconds > 59 in HH:MM:SS
|
|
])
|
|
def test_parse_time_invalid_inputs_raise_error(invalid_time_str, expected_error_msg_part):
|
|
"""
|
|
Tests that invalid time string formats raise a ValueError
|
|
with an informative message.
|
|
"""
|
|
with pytest.raises(ValueError) as excinfo:
|
|
parse_time_to_seconds(invalid_time_str)
|
|
|
|
# Check that the exception message contains the expected substring
|
|
assert expected_error_msg_part in str(excinfo.value)
|
|
|
|
|
|
def test_parse_time_non_string_input_raises_error():
|
|
"""Tests that non-string, non-None inputs raise a TypeError."""
|
|
with pytest.raises(TypeError):
|
|
parse_time_to_seconds(123) # Pass an integer
|
|
|
|
with pytest.raises(TypeError):
|
|
parse_time_to_seconds([1, 2, 3]) # Pass a list
|
|
|
|
with pytest.raises(TypeError):
|
|
parse_time_to_seconds({"time": "10"}) # Pass a dict
|
|
|
|
|
|
# --- Test Cases for parse_note_to_frequency ---
|
|
|
|
@pytest.mark.parametrize("note, octave, expected_freq", [
|
|
# Reference notes
|
|
("A", 4, 440.0), # A4 standard pitch
|
|
("C", 4, 261.63), # Middle C
|
|
("C", 0, 16.35), # Very low C
|
|
|
|
# Different notations
|
|
("C#", 4, 277.18), # C sharp
|
|
("c sharp", 4, 277.18), # C sharp with text
|
|
("c sharp", 4, 277.18), # C sharp with extra space
|
|
("Db", 4, 277.18), # D flat (same as C#)
|
|
("d flat", 4, 277.18), # D flat with text
|
|
("d b", 4, 277.18), # D flat with extra space
|
|
|
|
# Different octaves
|
|
("A", 5, 880.0), # One octave higher
|
|
("A", 3, 220.0), # One octave lower
|
|
])
|
|
def test_parse_note_valid_inputs(note, octave, expected_freq):
|
|
"""Tests that valid note strings are parsed to the correct frequencies."""
|
|
assert parse_note_to_frequency(note, octave) == pytest.approx(expected_freq, rel=0.001)
|
|
|
|
|
|
@pytest.mark.parametrize("invalid_note_str", [
|
|
"H", # Not a valid note letter
|
|
"C##", # Double sharp not supported by this simple parser
|
|
"Dbb", # Double flat not supported
|
|
"A Sharps", # Invalid text
|
|
"123", # Not a note
|
|
"", # Empty string
|
|
])
|
|
def test_parse_note_invalid_notes_raise_error(invalid_note_str):
|
|
"""Tests that invalid note names raise ValueError."""
|
|
with pytest.raises(ValueError, match="Invalid note name"):
|
|
parse_note_to_frequency(invalid_note_str, 4)
|
|
|
|
|
|
def test_parse_note_invalid_type_raises_error():
|
|
"""Tests that non-string inputs raise TypeError."""
|
|
with pytest.raises(TypeError):
|
|
parse_note_to_frequency(123, 4)
|
|
with pytest.raises(TypeError):
|
|
parse_note_to_frequency(None, 4)
|