@@ -0,0 +1,64 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from generator.practice.generate import generate_practice_scores, key_file_name
|
||||
from generator.score import slugify, validate_generated_tree
|
||||
from generator.summary import validate_practice_variants
|
||||
from generator.transposition import TARGET_KEYS
|
||||
from tests.test_musicxml import xml_note, xml_score
|
||||
|
||||
class CatalogueTests(unittest.TestCase):
|
||||
def test_every_practice_source_has_its_own_complete_output(self):
|
||||
source = Path('data/practice')
|
||||
sources = sorted(source.rglob('*.xml'))
|
||||
self.assertTrue(sources)
|
||||
expected = set()
|
||||
for path in sources:
|
||||
relative = path.relative_to(source)
|
||||
self.assertEqual(len(relative.parts), 3, str(path))
|
||||
self.assertIn(relative.parts[0], ('chord', 'melody'), str(path))
|
||||
for key in TARGET_KEYS:
|
||||
expected.add(relative.parent / slugify(path.stem) / key_file_name(key))
|
||||
self.assertEqual(len(expected), len(sources) * len(TARGET_KEYS))
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
output = Path(temporary)
|
||||
self.assertEqual(generate_practice_scores(source, output), len(expected))
|
||||
self.assertEqual({p.relative_to(output) for p in output.rglob('*.json')}, expected)
|
||||
validate_practice_variants(output)
|
||||
validate_generated_tree(output)
|
||||
def test_numbered_paths_and_duplicate_titles_remain_distinct(self):
|
||||
names = ('chord/001_lesson/001-cycles.xml', 'chord/001_lesson/010-cycles.xml', 'chord/002_lesson/001-cycles.xml', 'melody/001_lesson/127-cycles.xml')
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
source, output = Path(temporary) / 'source', Path(temporary) / 'output'
|
||||
for name in names:
|
||||
path = source / name
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(xml_score(xml_note()), encoding='utf-8')
|
||||
self.assertEqual(generate_practice_scores(source, output), len(names) * len(TARGET_KEYS))
|
||||
for name in names:
|
||||
directory = output / Path(name).with_suffix('')
|
||||
self.assertEqual({p.name for p in directory.glob('*.json')}, {key_file_name(key) for key in TARGET_KEYS})
|
||||
self.assertEqual(json.loads((directory / 'c.json').read_text())['metadata']['title'], 'Fixture')
|
||||
def test_invalid_source_locations_fail_before_writing(self):
|
||||
for name in ('chords/001_lesson/001-exercise.xml', 'chord/001-exercise.xml', 'melody/001_lesson/extra/001-exercise.xml'):
|
||||
with self.subTest(name=name), tempfile.TemporaryDirectory() as temporary:
|
||||
source, output = Path(temporary) / 'source', Path(temporary) / 'output'
|
||||
for relative in ('chord/001_lesson/001-valid.xml', name):
|
||||
path = source / relative
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(xml_score(xml_note()), encoding='utf-8')
|
||||
with self.assertRaisesRegex(ValueError, 'practice source must be stored'):
|
||||
generate_practice_scores(source, output)
|
||||
self.assertFalse(output.exists())
|
||||
def test_normalized_filename_collisions_fail_before_writing(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
source, output = Path(temporary) / 'source', Path(temporary) / 'output'
|
||||
lesson = source / 'chord' / '001_lesson'
|
||||
lesson.mkdir(parents=True)
|
||||
for name in ('001-Cycles.xml', '001_cycles.xml'):
|
||||
(lesson / name).write_text(xml_score(xml_note()), encoding='utf-8')
|
||||
with self.assertRaisesRegex(ValueError, 'output path collides'):
|
||||
generate_practice_scores(source, output)
|
||||
self.assertFalse(output.exists())
|
||||
Reference in New Issue
Block a user