Skip to content

Commit 1d5fbef

Browse files
mrcfpscmccandless
authored andcommitted
scale-generator: update tests to v1.0.0 (exercism#1328)
* scale-generator: update tests to canonical v1.0.0 * Remove name-related tests * Simplify test assertions * scale-generator: update stub file * scale-generator: improve example to pass tests v1.0.0 * scale-generator: add canonical data version
1 parent fece5b2 commit 1d5fbef

3 files changed

Lines changed: 44 additions & 80 deletions

File tree

exercises/scale-generator/example.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,21 @@ class Scale(object):
88
FLAT_KEYS = ['F', 'Bb', 'Eb', 'Ab', 'Db', 'Gb', 'd', 'g', 'c', 'f', 'bb',
99
'eb']
1010

11-
def __init__(self, tonic, scale_name, pattern=None):
11+
def __init__(self, tonic, intervals=None):
1212
self.tonic = tonic.capitalize()
13-
self.name = self.tonic + ' ' + scale_name
14-
self.pattern = pattern
13+
self.intervals = intervals
1514
self.chromatic_scale = (self.FLAT_CHROMATIC_SCALE
1615
if tonic in self.FLAT_KEYS
1716
else self.CHROMATIC_SCALE)
1817
self.pitches = self._assign_pitches()
1918

2019
def _assign_pitches(self):
21-
if self.pattern is None:
20+
if self.intervals is None:
2221
return self._reorder_chromatic_scale()
2322
last_index = 0
2423
pitches = []
2524
scale = self._reorder_chromatic_scale()
26-
for i, interval in enumerate(self.pattern):
25+
for i, interval in enumerate(self.intervals):
2726
pitches.append(scale[last_index])
2827
last_index += self.ASCENDING_INTERVALS.index(interval) + 1
2928
if pitches[0] != scale[last_index % len(scale)]:
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
class Scale(object):
2-
def __init__(self, tonic, scale_name, pattern=None):
3-
pass
2+
def __init__(self, tonic, intervals=None):
3+
self.pitches = None

exercises/scale-generator/scale_generator_test.py

Lines changed: 38 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -3,121 +3,86 @@
33
from scale_generator import Scale
44

55

6+
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0
7+
68
class ScaleGeneratorTest(unittest.TestCase):
79

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):
3623
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)
3925

40-
def test_another_major_scale(self):
41-
major = Scale('G', 'major', 'MMmMMMm')
26+
def test_major_scale_with_sharps(self):
4227
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)
4533

46-
def test_minor_scale(self):
47-
minor = Scale('f#', 'minor', 'MmMMmMM')
34+
def test_minor_scale_with_sharps(self):
4835
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)
5137

52-
def test_another_minor_scale(self):
53-
minor = Scale('bb', 'minor', 'MmMMmMM')
38+
def test_minor_scale_with_flats(self):
5439
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)
5741

5842
def test_dorian_mode(self):
59-
dorian = Scale('d', 'dorian', 'MmMMMmM')
6043
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)
6345

6446
def test_mixolydian_mode(self):
65-
mixolydian = Scale('Eb', 'mixolydian', 'MMmMMmM')
6647
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)
6949

7050
def test_lydian_mode(self):
71-
lydian = Scale('a', 'lydian', 'MMMmMMm')
7251
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)
7553

7654
def test_phrygian_mode(self):
77-
phrygian = Scale('e', 'phrygian', 'mMMMmMM')
7855
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)
8157

8258
def test_locrian_mode(self):
83-
locrian = Scale('g', 'locrian', 'mMMmMMM')
8459
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)
8761

8862
def test_harmonic_minor(self):
89-
harmonic_minor = Scale('d', 'harmonic_minor', 'MmMMmAm')
9063
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)
9365

9466
def test_octatonic(self):
95-
octatonic = Scale('C', 'octatonic', 'MmMmMmMm')
9667
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)
9969

10070
def test_hexatonic(self):
101-
hexatonic = Scale('Db', 'hexatonic', 'MMMMMM')
10271
expected = ['Db', 'Eb', 'F', 'G', 'A', 'B']
103-
actual = hexatonic.pitches
104-
self.assertEqual(expected, actual)
72+
self.assertEqual(Scale('Db', 'MMMMMM').pitches, expected)
10573

10674
def test_pentatonic(self):
107-
pentatonic = Scale('A', 'pentatonic', 'MMAMA')
10875
expected = ['A', 'B', 'C#', 'E', 'F#']
109-
actual = pentatonic.pitches
110-
self.assertEqual(expected, actual)
76+
self.assertEqual(Scale('A', 'MMAMA').pitches, expected)
11177

11278
def test_enigmatic(self):
113-
enigmatic = Scale('G', 'enigmatic', 'mAMMMmm')
11479
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)
11781

82+
# Track-specific tests
11883
def test_brokeninterval(self):
11984
with self.assertRaisesWithMessage(ValueError):
120-
Scale('G', 'enigmatic', 'mAMMMmM')
85+
Scale('G', 'mAMMMmM')
12186

12287
# Utility functions
12388
def setUp(self):

0 commit comments

Comments
 (0)