|
3 | 3 | from scale_generator import Scale |
4 | 4 |
|
5 | 5 |
|
| 6 | +# Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0 |
| 7 | + |
6 | 8 | class ScaleGeneratorTest(unittest.TestCase): |
7 | 9 |
|
8 | | - def test_naming_scale(self): |
9 | | - chromatic = Scale('c', 'chromatic') |
10 | | - expected = 'C chromatic' |
11 | | - actual = chromatic.name |
12 | | - self.assertEqual(expected, actual) |
13 | | - |
14 | | - def test_chromatic_scale(self): |
15 | | - chromatic = Scale('C', 'chromatic') |
16 | | - expected = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', |
17 | | - 'B'] |
18 | | - actual = chromatic.pitches |
19 | | - self.assertEqual(expected, actual) |
20 | | - |
21 | | - def test_another_chromatic_scale(self): |
22 | | - chromatic = Scale('F', 'chromatic') |
23 | | - expected = ['F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', |
24 | | - 'E'] |
25 | | - actual = chromatic.pitches |
26 | | - self.assertEqual(expected, actual) |
27 | | - |
28 | | - def test_naming_major_scale(self): |
29 | | - major = Scale('G', 'major', 'MMmMMMm') |
30 | | - expected = 'G major' |
31 | | - actual = major.name |
32 | | - self.assertEqual(expected, actual) |
33 | | - |
34 | | - def test_major_scale(self): |
35 | | - major = Scale('C', 'major', 'MMmMMMm') |
| 10 | + # Test chromatic scales |
| 11 | + def test_chromatic_scale_with_sharps(self): |
| 12 | + expected = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', |
| 13 | + 'G', 'G#', 'A', 'A#', 'B'] |
| 14 | + self.assertEqual(Scale('C').pitches, expected) |
| 15 | + |
| 16 | + def test_chromatic_scale_with_flats(self): |
| 17 | + expected = ['F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B', |
| 18 | + 'C', 'Db', 'D', 'Eb', 'E'] |
| 19 | + self.assertEqual(Scale('F').pitches, expected) |
| 20 | + |
| 21 | + # Test scales with specified intervals |
| 22 | + def test_simple_major_scale(self): |
36 | 23 | expected = ['C', 'D', 'E', 'F', 'G', 'A', 'B'] |
37 | | - actual = major.pitches |
38 | | - self.assertEqual(expected, actual) |
| 24 | + self.assertEqual(Scale('C', 'MMmMMMm').pitches, expected) |
39 | 25 |
|
40 | | - def test_another_major_scale(self): |
41 | | - major = Scale('G', 'major', 'MMmMMMm') |
| 26 | + def test_major_scale_with_sharps(self): |
42 | 27 | expected = ['G', 'A', 'B', 'C', 'D', 'E', 'F#'] |
43 | | - actual = major.pitches |
44 | | - self.assertEqual(expected, actual) |
| 28 | + self.assertEqual(Scale('G', 'MMmMMMm').pitches, expected) |
| 29 | + |
| 30 | + def test_major_scale_with_flats(self): |
| 31 | + expected = ['F', 'G', 'A', 'Bb', 'C', 'D', 'E'] |
| 32 | + self.assertEqual(Scale('F', 'MMmMMMm').pitches, expected) |
45 | 33 |
|
46 | | - def test_minor_scale(self): |
47 | | - minor = Scale('f#', 'minor', 'MmMMmMM') |
| 34 | + def test_minor_scale_with_sharps(self): |
48 | 35 | expected = ['F#', 'G#', 'A', 'B', 'C#', 'D', 'E'] |
49 | | - actual = minor.pitches |
50 | | - self.assertEqual(expected, actual) |
| 36 | + self.assertEqual(Scale('f#', 'MmMMmMM').pitches, expected) |
51 | 37 |
|
52 | | - def test_another_minor_scale(self): |
53 | | - minor = Scale('bb', 'minor', 'MmMMmMM') |
| 38 | + def test_minor_scale_with_flats(self): |
54 | 39 | expected = ['Bb', 'C', 'Db', 'Eb', 'F', 'Gb', 'Ab'] |
55 | | - actual = minor.pitches |
56 | | - self.assertEqual(expected, actual) |
| 40 | + self.assertEqual(Scale('bb', 'MmMMmMM').pitches, expected) |
57 | 41 |
|
58 | 42 | def test_dorian_mode(self): |
59 | | - dorian = Scale('d', 'dorian', 'MmMMMmM') |
60 | 43 | expected = ['D', 'E', 'F', 'G', 'A', 'B', 'C'] |
61 | | - actual = dorian.pitches |
62 | | - self.assertEqual(expected, actual) |
| 44 | + self.assertEqual(Scale('d', 'MmMMMmM').pitches, expected) |
63 | 45 |
|
64 | 46 | def test_mixolydian_mode(self): |
65 | | - mixolydian = Scale('Eb', 'mixolydian', 'MMmMMmM') |
66 | 47 | expected = ['Eb', 'F', 'G', 'Ab', 'Bb', 'C', 'Db'] |
67 | | - actual = mixolydian.pitches |
68 | | - self.assertEqual(expected, actual) |
| 48 | + self.assertEqual(Scale('Eb', 'MMmMMmM').pitches, expected) |
69 | 49 |
|
70 | 50 | def test_lydian_mode(self): |
71 | | - lydian = Scale('a', 'lydian', 'MMMmMMm') |
72 | 51 | expected = ['A', 'B', 'C#', 'D#', 'E', 'F#', 'G#'] |
73 | | - actual = lydian.pitches |
74 | | - self.assertEqual(expected, actual) |
| 52 | + self.assertEqual(Scale('a', 'MMMmMMm').pitches, expected) |
75 | 53 |
|
76 | 54 | def test_phrygian_mode(self): |
77 | | - phrygian = Scale('e', 'phrygian', 'mMMMmMM') |
78 | 55 | expected = ['E', 'F', 'G', 'A', 'B', 'C', 'D'] |
79 | | - actual = phrygian.pitches |
80 | | - self.assertEqual(expected, actual) |
| 56 | + self.assertEqual(Scale('e', 'mMMMmMM').pitches, expected) |
81 | 57 |
|
82 | 58 | def test_locrian_mode(self): |
83 | | - locrian = Scale('g', 'locrian', 'mMMmMMM') |
84 | 59 | expected = ['G', 'Ab', 'Bb', 'C', 'Db', 'Eb', 'F'] |
85 | | - actual = locrian.pitches |
86 | | - self.assertEqual(expected, actual) |
| 60 | + self.assertEqual(Scale('g', 'mMMmMMM').pitches, expected) |
87 | 61 |
|
88 | 62 | def test_harmonic_minor(self): |
89 | | - harmonic_minor = Scale('d', 'harmonic_minor', 'MmMMmAm') |
90 | 63 | expected = ['D', 'E', 'F', 'G', 'A', 'Bb', 'Db'] |
91 | | - actual = harmonic_minor.pitches |
92 | | - self.assertEqual(expected, actual) |
| 64 | + self.assertEqual(Scale('d', 'MmMMmAm').pitches, expected) |
93 | 65 |
|
94 | 66 | def test_octatonic(self): |
95 | | - octatonic = Scale('C', 'octatonic', 'MmMmMmMm') |
96 | 67 | expected = ['C', 'D', 'D#', 'F', 'F#', 'G#', 'A', 'B'] |
97 | | - actual = octatonic.pitches |
98 | | - self.assertEqual(expected, actual) |
| 68 | + self.assertEqual(Scale('C', 'MmMmMmMm').pitches, expected) |
99 | 69 |
|
100 | 70 | def test_hexatonic(self): |
101 | | - hexatonic = Scale('Db', 'hexatonic', 'MMMMMM') |
102 | 71 | expected = ['Db', 'Eb', 'F', 'G', 'A', 'B'] |
103 | | - actual = hexatonic.pitches |
104 | | - self.assertEqual(expected, actual) |
| 72 | + self.assertEqual(Scale('Db', 'MMMMMM').pitches, expected) |
105 | 73 |
|
106 | 74 | def test_pentatonic(self): |
107 | | - pentatonic = Scale('A', 'pentatonic', 'MMAMA') |
108 | 75 | expected = ['A', 'B', 'C#', 'E', 'F#'] |
109 | | - actual = pentatonic.pitches |
110 | | - self.assertEqual(expected, actual) |
| 76 | + self.assertEqual(Scale('A', 'MMAMA').pitches, expected) |
111 | 77 |
|
112 | 78 | def test_enigmatic(self): |
113 | | - enigmatic = Scale('G', 'enigmatic', 'mAMMMmm') |
114 | 79 | expected = ['G', 'G#', 'B', 'C#', 'D#', 'F', 'F#'] |
115 | | - actual = enigmatic.pitches |
116 | | - self.assertEqual(expected, actual) |
| 80 | + self.assertEqual(Scale('G', 'mAMMMmm').pitches, expected) |
117 | 81 |
|
| 82 | + # Track-specific tests |
118 | 83 | def test_brokeninterval(self): |
119 | 84 | with self.assertRaisesWithMessage(ValueError): |
120 | | - Scale('G', 'enigmatic', 'mAMMMmM') |
| 85 | + Scale('G', 'mAMMMmM') |
121 | 86 |
|
122 | 87 | # Utility functions |
123 | 88 | def setUp(self): |
|
0 commit comments