trackler 2.2.1.52 → 2.2.1.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/exercises/leap/canonical-data.json +2 -2
- data/tracks/cfml/tasks/FormatConfig.cfc +6 -4
- data/tracks/cfml/tasks/GenerateReadme.cfc +197 -0
- data/tracks/cfml/tasks/ScaffoldExercise.cfc +6 -0
- data/tracks/csharp/config.json +1 -1
- data/tracks/delphi/exercises/leap/uLeapTests.pas +1 -1
- data/tracks/fsharp/exercises/clock/Clock.fs +1 -1
- data/tracks/fsharp/exercises/clock/ClockTest.fs +239 -61
- data/tracks/fsharp/exercises/clock/Example.fs +3 -3
- data/tracks/fsharp/exercises/dominoes/DominoesTest.fs +29 -26
- data/tracks/fsharp/exercises/largest-series-product/LargestSeriesProductTest.fs +30 -15
- data/tracks/fsharp/exercises/leap/LeapTest.fs +2 -2
- data/tracks/fsharp/exercises/rectangles/Example.fs +1 -1
- data/tracks/fsharp/exercises/rectangles/Rectangles.fs +1 -1
- data/tracks/fsharp/exercises/rectangles/RectanglesTest.fs +66 -43
- data/tracks/fsharp/generators/Generators.fs +85 -1
- data/tracks/java/scripts/canonical_data_check.sh +8 -0
- data/tracks/kotlin/.gitignore +1 -0
- data/tracks/kotlin/exercises/acronym/.meta/version +1 -0
- data/tracks/kotlin/exercises/acronym/src/test/kotlin/AcronymTest.kt +9 -10
- data/tracks/kotlin/exercises/all-your-base/.meta/version +1 -1
- data/tracks/kotlin/exercises/all-your-base/src/test/kotlin/BaseConverterTest.kt +20 -20
- data/tracks/kotlin/exercises/allergies/.meta/version +1 -0
- data/tracks/kotlin/exercises/allergies/src/test/kotlin/AllergiesTest.kt +19 -72
- data/tracks/kotlin/exercises/anagram/.meta/src/reference/kotlin/Anagram.kt +7 -4
- data/tracks/kotlin/exercises/anagram/.meta/version +1 -0
- data/tracks/kotlin/exercises/anagram/src/test/kotlin/AnagramTest.kt +76 -29
- data/tracks/kotlin/exercises/atbash-cipher/.meta/version +1 -0
- data/tracks/kotlin/exercises/atbash-cipher/src/test/kotlin/AtbashTest.kt +6 -3
- data/tracks/kotlin/exercises/beer-song/.meta/version +1 -0
- data/tracks/kotlin/exercises/beer-song/src/test/kotlin/BeerSongTest.kt +21 -46
- data/tracks/kotlin/exercises/binary-search/.meta/version +1 -0
- data/tracks/kotlin/exercises/binary-search/src/test/kotlin/BinarySearchTest.kt +30 -19
- data/tracks/kotlin/exercises/bob/.meta/src/reference/kotlin/Bob.kt +8 -7
- data/tracks/kotlin/exercises/bob/.meta/version +1 -0
- data/tracks/kotlin/exercises/bob/src/test/kotlin/BobTest.kt +57 -15
- data/tracks/kotlin/exercises/bracket-push/.meta/version +1 -0
- data/tracks/kotlin/exercises/bracket-push/src/test/kotlin/BracketPushTest.kt +3 -1
- data/tracks/kotlin/exercises/collatz-conjecture/.meta/version +1 -1
- data/tracks/kotlin/exercises/difference-of-squares/.meta/version +1 -0
- data/tracks/kotlin/exercises/difference-of-squares/src/test/kotlin/SquaresTest.kt +10 -23
- data/tracks/kotlin/exercises/etl/.meta/src/reference/kotlin/ETL.kt +7 -1
- data/tracks/kotlin/exercises/etl/.meta/version +1 -0
- data/tracks/kotlin/exercises/etl/src/test/kotlin/ETLTest.kt +10 -10
- data/tracks/kotlin/exercises/flatten-array/.meta/version +1 -0
- data/tracks/kotlin/exercises/flatten-array/src/test/kotlin/FlattenerTest.kt +8 -16
- data/tracks/kotlin/exercises/gigasecond/.meta/version +1 -0
- data/tracks/kotlin/exercises/gigasecond/src/test/kotlin/GigasecondTest.kt +1 -1
- data/tracks/kotlin/exercises/hamming/.meta/src/reference/kotlin/Hamming.kt +1 -1
- data/tracks/kotlin/exercises/hamming/.meta/version +1 -1
- data/tracks/kotlin/exercises/hamming/src/test/kotlin/HammingTest.kt +4 -4
- data/tracks/kotlin/exercises/hello-world/.meta/version +1 -0
- data/tracks/kotlin/exercises/hello-world/src/test/kotlin/HelloWorldTest.kt +1 -1
- data/tracks/kotlin/exercises/isogram/.meta/version +1 -0
- data/tracks/kotlin/exercises/isogram/src/test/kotlin/IsogramTest.kt +5 -8
- data/tracks/kotlin/exercises/largest-series-product/.meta/src/reference/kotlin/Series.kt +2 -3
- data/tracks/kotlin/exercises/largest-series-product/.meta/version +1 -0
- data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesTest.kt +97 -0
- data/tracks/kotlin/exercises/leap/.meta/version +1 -0
- data/tracks/kotlin/exercises/leap/src/test/kotlin/LeapTest.kt +8 -26
- data/tracks/kotlin/exercises/list-ops/.meta/version +1 -1
- data/tracks/kotlin/exercises/luhn/.meta/version +1 -0
- data/tracks/kotlin/exercises/luhn/src/test/kotlin/LuhnTest.kt +0 -3
- data/tracks/kotlin/exercises/nth-prime/.meta/version +1 -0
- data/tracks/kotlin/exercises/nth-prime/src/test/kotlin/PrimeTest.kt +0 -2
- data/tracks/kotlin/exercises/nucleotide-count/.meta/src/reference/kotlin/{DNA.kt → Dna.kt} +3 -8
- data/tracks/kotlin/exercises/nucleotide-count/.meta/version +1 -0
- data/tracks/kotlin/exercises/nucleotide-count/src/test/kotlin/DnaTest.kt +48 -0
- data/tracks/kotlin/exercises/pangram/.meta/src/reference/kotlin/{Pangrams.kt → Pangram.kt} +1 -1
- data/tracks/kotlin/exercises/pangram/.meta/version +1 -1
- data/tracks/kotlin/exercises/pangram/src/test/kotlin/PangramTest.kt +15 -9
- data/tracks/kotlin/exercises/pascals-triangle/.meta/version +1 -0
- data/tracks/kotlin/exercises/pascals-triangle/src/test/kotlin/PascalsTriangleTest.kt +32 -14
- data/tracks/kotlin/exercises/perfect-numbers/.meta/src/reference/kotlin/NaturalNumber.kt +1 -1
- data/tracks/kotlin/exercises/perfect-numbers/.meta/version +1 -0
- data/tracks/kotlin/exercises/perfect-numbers/src/test/kotlin/{PerfectNumbersTest.kt → NaturalNumberTest.kt} +25 -7
- data/tracks/kotlin/exercises/phone-number/.meta/src/reference/kotlin/PhoneNumber.kt +15 -7
- data/tracks/kotlin/exercises/phone-number/.meta/version +1 -0
- data/tracks/kotlin/exercises/phone-number/src/test/kotlin/PhoneNumberTest.kt +46 -29
- data/tracks/kotlin/exercises/pig-latin/.meta/src/reference/kotlin/PigLatin.kt +2 -2
- data/tracks/kotlin/exercises/pig-latin/.meta/version +1 -0
- data/tracks/kotlin/exercises/pig-latin/src/test/kotlin/PigLatinTest.kt +21 -10
- data/tracks/kotlin/exercises/raindrops/.meta/version +1 -0
- data/tracks/kotlin/exercises/raindrops/src/test/kotlin/RaindropsTest.kt +19 -26
- data/tracks/kotlin/exercises/react/.meta/version +1 -0
- data/tracks/kotlin/exercises/react/src/test/kotlin/ReactTest.kt +11 -4
- data/tracks/kotlin/exercises/robot-simulator/.meta/version +1 -1
- data/tracks/kotlin/exercises/roman-numerals/.meta/version +1 -0
- data/tracks/kotlin/exercises/roman-numerals/src/test/kotlin/RomanNumeralTest.kt +1 -2
- data/tracks/kotlin/exercises/rotational-cipher/.meta/version +1 -1
- data/tracks/kotlin/exercises/rotational-cipher/src/test/kotlin/RotationalCipherTest.kt +7 -7
- data/tracks/kotlin/exercises/scrabble-score/.meta/src/reference/kotlin/{Scrabble.kt → ScrabbleScore.kt} +1 -1
- data/tracks/kotlin/exercises/scrabble-score/.meta/version +1 -0
- data/tracks/kotlin/exercises/scrabble-score/src/test/kotlin/ScrabbleScoreTest.kt +9 -7
- data/tracks/kotlin/exercises/sieve/.meta/version +1 -0
- data/tracks/kotlin/exercises/sieve/src/test/kotlin/SieveTest.kt +8 -0
- data/tracks/kotlin/exercises/space-age/.meta/version +1 -0
- data/tracks/kotlin/exercises/space-age/src/test/kotlin/SpaceAgeTest.kt +1 -16
- data/tracks/kotlin/exercises/sum-of-multiples/.meta/version +1 -0
- data/tracks/kotlin/exercises/sum-of-multiples/src/test/kotlin/SumOfMultiplesTest.kt +7 -7
- data/tracks/kotlin/exercises/triangle/.meta/version +1 -0
- data/tracks/kotlin/exercises/two-fer/.meta/version +1 -0
- data/tracks/kotlin/exercises/two-fer/src/test/kotlin/TwoferTest.kt +0 -1
- data/tracks/kotlin/exercises/word-count/.meta/src/reference/kotlin/WordCount.kt +6 -2
- data/tracks/kotlin/exercises/word-count/.meta/version +1 -0
- data/tracks/kotlin/exercises/word-count/src/test/kotlin/WordCountTest.kt +31 -9
- data/tracks/kotlin/scripts/canonical_data_check.sh +8 -0
- data/tracks/perl6/exercises/leap/leap.t +2 -2
- data/tracks/php/config.json +16 -0
- data/tracks/php/exercises/crypto-square/crypto-square_test.php +50 -0
- data/tracks/php/exercises/crypto-square/example.php +32 -0
- data/tracks/php/exercises/meetup/README.md +21 -0
- data/tracks/php/exercises/meetup/example.php +19 -0
- data/tracks/php/exercises/meetup/meetup_test.php +577 -0
- data/tracks/python/README.md +7 -5
- data/tracks/python/config.json +36 -27
- data/tracks/python/docs/TESTS.md +36 -12
- data/tracks/python/exercises/complex-numbers/complex_numbers_test.py +1 -1
- data/tracks/python/exercises/diffie-hellman/.meta/hints.md +16 -0
- data/tracks/python/exercises/diffie-hellman/README.md +15 -2
- data/tracks/python/exercises/error-handling/README.md +23 -0
- data/tracks/python/exercises/error-handling/error_handling.py +14 -0
- data/tracks/python/exercises/error-handling/error_handling_test.py +66 -0
- data/tracks/python/exercises/error-handling/example.py +21 -0
- data/tracks/python/exercises/forth/forth_test.py +1 -1
- data/tracks/python/exercises/isogram/isogram_test.py +5 -3
- data/tracks/python/exercises/leap/leap_test.py +2 -2
- data/tracks/python/exercises/rotational-cipher/rotational_cipher_test.py +4 -4
- data/tracks/python/exercises/simple-cipher/.meta/hints.md +16 -0
- data/tracks/python/exercises/simple-cipher/README.md +17 -0
- data/tracks/python/exercises/sum-of-multiples/sum_of_multiples_test.py +4 -1
- data/tracks/python/exercises/twelve-days/example.py +3 -3
- data/tracks/python/exercises/twelve-days/twelve_days.py +2 -2
- metadata +53 -9
- data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesInvalidInputTest.kt +0 -30
- data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesValidInputTest.kt +0 -34
- data/tracks/kotlin/exercises/nucleotide-count/src/test/kotlin/NucleotideTest.kt +0 -87
data/tracks/python/README.md
CHANGED
|
@@ -19,10 +19,12 @@ A list of missing exercise can be found here: http://exercism.io/languages/pytho
|
|
|
19
19
|
|
|
20
20
|
### Conventions
|
|
21
21
|
|
|
22
|
-
- We use minimalistic stub files for all exercises (#272).
|
|
22
|
+
- We use minimalistic stub files for all exercises ([#272](https://github.com/exercism/python/issues/272)).
|
|
23
23
|
- We use `unittest` (Python Standard Library) and no 3rd-party-framework.
|
|
24
|
-
- We use the parameter order `self.assertEqual(actual, expected)` (#440).
|
|
25
|
-
- We use context managers (`with self.assertRaises(\<exception type\>):`) for testing for exceptions (#477).
|
|
24
|
+
- We use the parameter order `self.assertEqual(actual, expected)` ([#440](https://github.com/exercism/python/issues/440)).
|
|
25
|
+
- We use context managers (`with self.assertRaises(\<exception type\>):`) for testing for exceptions ([#477](https://github.com/exercism/python/issues/477)).
|
|
26
|
+
- We use `assertIs(actual, True)` and `assertIs(actual, False)` rather than `assertTrue(actual)` or `assertFalse(actual)` ([#419](https://github.com/exercism/python/pull/419)).
|
|
27
|
+
- We use a comment string in the test file to reference the version of the exercise's `canonical-data.json` that tests were adapted from (wording can be found in: [#784](https://github.com/exercism/python/issues/784)).
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
### Testing
|
|
@@ -56,12 +58,12 @@ It will automatically check the code style, the problem configuration, and run t
|
|
|
56
58
|
|
|
57
59
|
## Pull Requests
|
|
58
60
|
|
|
59
|
-
We :heart: pull requests!
|
|
61
|
+
We :heart: pull requests!
|
|
60
62
|
We even :sparkling_heart: them if they contain well written commit messages!
|
|
61
63
|
|
|
62
64
|
Please write the first line of your commit message in the following style:
|
|
63
65
|
|
|
64
|
-
```exercise-name: Change some things```
|
|
66
|
+
```exercise-name: Change some things```
|
|
65
67
|
|
|
66
68
|
Please try to follow the [The seven rules of a great Git commit message](https://chris.beams.io/posts/git-commit/#seven-rules) like to capitalize the subject line and use the imperative mood. If there are more details to add, put those into the body of the commit message.
|
|
67
69
|
|
data/tracks/python/config.json
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"unlocked_by": null,
|
|
10
10
|
"difficulty": 1,
|
|
11
11
|
"topics": [
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
12
|
+
"conditionals",
|
|
13
|
+
"optional_values",
|
|
14
|
+
"text_formatting"
|
|
15
15
|
]
|
|
16
16
|
},
|
|
17
17
|
{
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"unlocked_by": null,
|
|
22
22
|
"difficulty": 1,
|
|
23
23
|
"topics": [
|
|
24
|
-
"
|
|
24
|
+
"conditionals",
|
|
25
25
|
"booleans",
|
|
26
26
|
"logic"
|
|
27
27
|
]
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"unlocked_by": null,
|
|
47
47
|
"difficulty": 1,
|
|
48
48
|
"topics": [
|
|
49
|
-
"
|
|
50
|
-
"
|
|
49
|
+
"loops",
|
|
50
|
+
"conditionals",
|
|
51
51
|
"strings",
|
|
52
52
|
"algorithms",
|
|
53
53
|
"filtering",
|
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
"unlocked_by": null,
|
|
62
62
|
"difficulty": 1,
|
|
63
63
|
"topics": [
|
|
64
|
-
"
|
|
65
|
-
"
|
|
64
|
+
"conditionals",
|
|
65
|
+
"loops",
|
|
66
66
|
"maps",
|
|
67
67
|
"strings",
|
|
68
68
|
"logic",
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
"unlocked_by": null,
|
|
77
77
|
"difficulty": 1,
|
|
78
78
|
"topics": [
|
|
79
|
-
"
|
|
80
|
-
"
|
|
79
|
+
"conditionals",
|
|
80
|
+
"loops",
|
|
81
81
|
"sequences",
|
|
82
82
|
"sets",
|
|
83
83
|
"strings",
|
|
@@ -96,8 +96,8 @@
|
|
|
96
96
|
"strings",
|
|
97
97
|
"algorithms",
|
|
98
98
|
"logic",
|
|
99
|
-
"
|
|
100
|
-
"
|
|
99
|
+
"pattern_recognition",
|
|
100
|
+
"text_formatting"
|
|
101
101
|
]
|
|
102
102
|
},
|
|
103
103
|
{
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
"topics": [
|
|
159
159
|
"strings",
|
|
160
160
|
"logic",
|
|
161
|
-
"
|
|
161
|
+
"loops"
|
|
162
162
|
]
|
|
163
163
|
},
|
|
164
164
|
{
|
|
@@ -479,8 +479,7 @@
|
|
|
479
479
|
"topics": [
|
|
480
480
|
"lists",
|
|
481
481
|
"searching",
|
|
482
|
-
"loops"
|
|
483
|
-
"iteration"
|
|
482
|
+
"loops"
|
|
484
483
|
]
|
|
485
484
|
},
|
|
486
485
|
{
|
|
@@ -672,7 +671,7 @@
|
|
|
672
671
|
"topics": [
|
|
673
672
|
"lists",
|
|
674
673
|
"parsing",
|
|
675
|
-
"
|
|
674
|
+
"transforming",
|
|
676
675
|
"loops",
|
|
677
676
|
"games"
|
|
678
677
|
]
|
|
@@ -908,7 +907,7 @@
|
|
|
908
907
|
"time",
|
|
909
908
|
"mathematics",
|
|
910
909
|
"logic",
|
|
911
|
-
"
|
|
910
|
+
"text_formatting"
|
|
912
911
|
]
|
|
913
912
|
},
|
|
914
913
|
{
|
|
@@ -919,7 +918,7 @@
|
|
|
919
918
|
"difficulty": 4,
|
|
920
919
|
"topics": [
|
|
921
920
|
"files",
|
|
922
|
-
"
|
|
921
|
+
"text_formatting",
|
|
923
922
|
"searching"
|
|
924
923
|
]
|
|
925
924
|
},
|
|
@@ -967,7 +966,7 @@
|
|
|
967
966
|
"difficulty": 3,
|
|
968
967
|
"topics": [
|
|
969
968
|
"strings",
|
|
970
|
-
"
|
|
969
|
+
"pattern_matching"
|
|
971
970
|
]
|
|
972
971
|
},
|
|
973
972
|
{
|
|
@@ -978,7 +977,7 @@
|
|
|
978
977
|
"difficulty": 3,
|
|
979
978
|
"topics": [
|
|
980
979
|
"strings",
|
|
981
|
-
"
|
|
980
|
+
"pattern_matching"
|
|
982
981
|
]
|
|
983
982
|
},
|
|
984
983
|
{
|
|
@@ -988,9 +987,9 @@
|
|
|
988
987
|
"unlocked_by": null,
|
|
989
988
|
"difficulty": 4,
|
|
990
989
|
"topics": [
|
|
991
|
-
"
|
|
992
|
-
"
|
|
993
|
-
"
|
|
990
|
+
"loops",
|
|
991
|
+
"arrays",
|
|
992
|
+
"algorithms"
|
|
994
993
|
]
|
|
995
994
|
},
|
|
996
995
|
{
|
|
@@ -1000,9 +999,9 @@
|
|
|
1000
999
|
"unlocked_by": null,
|
|
1001
1000
|
"difficulty": 1,
|
|
1002
1001
|
"topics": [
|
|
1003
|
-
"
|
|
1004
|
-
"
|
|
1005
|
-
"
|
|
1002
|
+
"conditionals",
|
|
1003
|
+
"optional_values",
|
|
1004
|
+
"text_formatting"
|
|
1006
1005
|
]
|
|
1007
1006
|
},
|
|
1008
1007
|
{
|
|
@@ -1012,7 +1011,7 @@
|
|
|
1012
1011
|
"unlocked_by": null,
|
|
1013
1012
|
"difficulty": 1,
|
|
1014
1013
|
"topics": [
|
|
1015
|
-
|
|
1014
|
+
"loops"
|
|
1016
1015
|
]
|
|
1017
1016
|
},
|
|
1018
1017
|
{
|
|
@@ -1089,6 +1088,16 @@
|
|
|
1089
1088
|
"trees"
|
|
1090
1089
|
]
|
|
1091
1090
|
},
|
|
1091
|
+
{
|
|
1092
|
+
"uuid": "3a2a947a-01b3-1e80-e32b-de1756fd88365adf12e",
|
|
1093
|
+
"slug": "error-handling",
|
|
1094
|
+
"core": false,
|
|
1095
|
+
"unlocked_by": null,
|
|
1096
|
+
"difficulty": 3,
|
|
1097
|
+
"topics": [
|
|
1098
|
+
"exception_handling"
|
|
1099
|
+
]
|
|
1100
|
+
},
|
|
1092
1101
|
{
|
|
1093
1102
|
"uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd",
|
|
1094
1103
|
"slug": "accumulate",
|
data/tracks/python/docs/TESTS.md
CHANGED
|
@@ -4,14 +4,38 @@ We recommend you install [pytest](http://pytest.org/latest/) and
|
|
|
4
4
|
[pytest-cache](http://pythonhosted.org/pytest-cache/). `pytest` is a testing
|
|
5
5
|
tool that will give you more flexibility over running your unit tests.
|
|
6
6
|
|
|
7
|
+
If you want to install `pytest` for Python 2, then use `pip`.
|
|
8
|
+
|
|
7
9
|
```bash
|
|
8
10
|
pip install pytest pytest-cache
|
|
9
11
|
```
|
|
12
|
+
If you instead want the version of `pytest` for Python 3, then use `pip3`.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip3 install pytest pytest-cache
|
|
16
|
+
```
|
|
10
17
|
|
|
11
18
|
If you get a `command not found` response from your system, you can find a
|
|
12
19
|
tutorial on how to install `pip`
|
|
13
20
|
[here](https://pip.pypa.io/en/stable/installing/).
|
|
14
21
|
|
|
22
|
+
**Note:** Whichever version of `pytest` you install last will be the default one used whenever `pytest` is executed, regardless of whether you have installed both versions.
|
|
23
|
+
|
|
24
|
+
If you want to check what the default version of `pytest` being used is, run the following:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pytest --version
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If you have either version of `pytest` installed and you want to specifically run one of the versions, you can run that version by using `python` with the `-m` flag.
|
|
31
|
+
|
|
32
|
+
For example, you could run the Python 3 version of pytest like so:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
$ python3 -m pytest --version
|
|
36
|
+
This is pytest version 3.2.3, imported from /usr/local/lib/python3.5/dist-packages/pytest.py
|
|
37
|
+
```
|
|
38
|
+
|
|
15
39
|
If you choose not to install `pytest`, you can still run tests individually and
|
|
16
40
|
skip the rest of this tutorial:
|
|
17
41
|
|
|
@@ -29,7 +53,7 @@ an example here), place yourself in the directory where that exercise has been
|
|
|
29
53
|
fetched and run:
|
|
30
54
|
|
|
31
55
|
```bash
|
|
32
|
-
|
|
56
|
+
pytest bob_test.py
|
|
33
57
|
```
|
|
34
58
|
|
|
35
59
|
**Note:** To run the tests you need to pass the name of the testsuite file to
|
|
@@ -56,7 +80,7 @@ The above will run all the tests, whether they fail or not. If you'd rather stop
|
|
|
56
80
|
the process and exit on the first failure, run:
|
|
57
81
|
|
|
58
82
|
```bash
|
|
59
|
-
|
|
83
|
+
pytest -x bob_test.py
|
|
60
84
|
```
|
|
61
85
|
|
|
62
86
|
### Failed Tests First
|
|
@@ -64,14 +88,14 @@ py.test -x bob_test.py
|
|
|
64
88
|
`pytest-cache` remembers which tests failed, and can run those tests first.
|
|
65
89
|
|
|
66
90
|
```bash
|
|
67
|
-
|
|
91
|
+
pytest --ff bob_test.py
|
|
68
92
|
```
|
|
69
93
|
|
|
70
94
|
### Running All Tests for All Exercises
|
|
71
95
|
|
|
72
96
|
```bash
|
|
73
97
|
cd exercism/python/
|
|
74
|
-
|
|
98
|
+
pytest
|
|
75
99
|
```
|
|
76
100
|
|
|
77
101
|
## Recommended Workflow
|
|
@@ -80,7 +104,7 @@ We recommend you run this command while working on exercises.
|
|
|
80
104
|
|
|
81
105
|
```bash
|
|
82
106
|
cd exercism/python/bob
|
|
83
|
-
|
|
107
|
+
pytest -x --ff bob_test.py
|
|
84
108
|
```
|
|
85
109
|
|
|
86
110
|
## PDB
|
|
@@ -89,28 +113,28 @@ Will drop you into the python debugger when a test fails. To learn how to use
|
|
|
89
113
|
pdb, check out the
|
|
90
114
|
[documentation](https://docs.python.org/3/library/pdb.html#debugger-commands).
|
|
91
115
|
|
|
92
|
-
You may also be interested in watching [Clayton Parker's "So you think you can
|
|
93
|
-
pdb?" PyCon 2015 talk](https://www.youtube.com/watch?v=P0pIW5tJrRM)
|
|
94
|
-
|
|
95
116
|
```bash
|
|
96
|
-
|
|
117
|
+
pytest --pdb bob_test.py
|
|
97
118
|
```
|
|
98
119
|
|
|
120
|
+
You may also be interested in watching [Clayton Parker's "So you think you can
|
|
121
|
+
pdb?" PyCon 2015 talk](https://www.youtube.com/watch?v=P0pIW5tJrRM).
|
|
122
|
+
|
|
99
123
|
## PEP8
|
|
100
124
|
|
|
101
125
|
PEP8 is the [Style Guide for Python
|
|
102
126
|
Code](https://www.python.org/dev/peps/pep-0008/). If you would like to test for
|
|
103
127
|
compliance to the style guide, install
|
|
104
|
-
[pytest-pep8](https://pypi.python.org/pypi/pytest-pep8)
|
|
128
|
+
[pytest-pep8](https://pypi.python.org/pypi/pytest-pep8).
|
|
105
129
|
|
|
106
130
|
```bash
|
|
107
131
|
pip install pytest-pep8
|
|
108
132
|
```
|
|
109
133
|
|
|
110
|
-
|
|
134
|
+
Then, just add the `--pep8` flag to your command
|
|
111
135
|
|
|
112
136
|
```bash
|
|
113
|
-
|
|
137
|
+
pytest --pep8 bob_test.py
|
|
114
138
|
```
|
|
115
139
|
|
|
116
140
|
Read the [pytest documentation](http://pytest.org/latest/contents.html#toc) and
|
|
@@ -55,7 +55,7 @@ class ComplexNumbersTest(unittest.TestCase):
|
|
|
55
55
|
self.assertEqual(first_input.sub(second_input).real, 2)
|
|
56
56
|
self.assertEqual(first_input.sub(second_input).imaginary, 0)
|
|
57
57
|
|
|
58
|
-
def
|
|
58
|
+
def test_subtract_numbers_with_real_and_imaginary_part(self):
|
|
59
59
|
first_input = ComplexNumber(1, 2)
|
|
60
60
|
second_input = ComplexNumber(-2, -2)
|
|
61
61
|
self.assertEqual(first_input.sub(second_input).real, 3)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
## Should I use random or secrets?
|
|
2
|
+
|
|
3
|
+
Python, as of version 3.6, includes two different random modules.
|
|
4
|
+
|
|
5
|
+
The module called `random` is pseudo-random, meaning it does not generate
|
|
6
|
+
true randomness, but follows an algorithm that simulates randomness.
|
|
7
|
+
Since random numbers are generated through a known algorithm, they are not truly random.
|
|
8
|
+
|
|
9
|
+
The `random` module is not correctly suited for cryptography and should not be used,
|
|
10
|
+
precisely because it is pseudo-random.
|
|
11
|
+
|
|
12
|
+
For this reason, in version 3.6, Python introduced the `secrets` module, which generates
|
|
13
|
+
cryptographically strong random numbers that provide the greater security required for cryptography.
|
|
14
|
+
|
|
15
|
+
Since this is only an exercise, `random` is fine to use, but note that **it would be
|
|
16
|
+
very insecure if actually used for cryptography.**
|
|
@@ -37,9 +37,22 @@ Bob calculates
|
|
|
37
37
|
The calculations produce the same result! Alice and Bob now share
|
|
38
38
|
secret s.
|
|
39
39
|
|
|
40
|
-
##
|
|
40
|
+
## Should I use random or secrets?
|
|
41
41
|
|
|
42
|
-
Python, as of version 3.6, includes two different random modules.
|
|
42
|
+
Python, as of version 3.6, includes two different random modules.
|
|
43
|
+
|
|
44
|
+
The module called `random` is pseudo-random, meaning it does not generate
|
|
45
|
+
true randomness, but follows an algorithm that simulates randomness.
|
|
46
|
+
Since random numbers are generated through a known algorithm, they are not truly random.
|
|
47
|
+
|
|
48
|
+
The `random` module is not correctly suited for cryptography and should not be used,
|
|
49
|
+
precisely because it is pseudo-random.
|
|
50
|
+
|
|
51
|
+
For this reason, in version 3.6, Python introduced the `secrets` module, which generates
|
|
52
|
+
cryptographically strong random numbers that provide the greater security required for cryptography.
|
|
53
|
+
|
|
54
|
+
Since this is only an exercise, `random` is fine to use, but note that **it would be
|
|
55
|
+
very insecure if actually used for cryptography.**
|
|
43
56
|
|
|
44
57
|
### Submitting Exercises
|
|
45
58
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Error Handling
|
|
2
|
+
|
|
3
|
+
Implement various kinds of error handling and resource management.
|
|
4
|
+
|
|
5
|
+
An important point of programming is how to handle errors and close
|
|
6
|
+
resources even if errors occur.
|
|
7
|
+
|
|
8
|
+
This exercise requires you to handle various errors. Because error handling
|
|
9
|
+
is rather programming language specific you'll have to refer to the tests
|
|
10
|
+
for your track to see what's exactly required.
|
|
11
|
+
|
|
12
|
+
### Submitting Exercises
|
|
13
|
+
|
|
14
|
+
Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/<exerciseName>` directory.
|
|
15
|
+
|
|
16
|
+
For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/python/bob/bob.py`.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
For more detailed information about running tests, code style and linting,
|
|
20
|
+
please see the [help page](http://exercism.io/languages/python).
|
|
21
|
+
|
|
22
|
+
## Submitting Incomplete Solutions
|
|
23
|
+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
import error_handling as er
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FileLike(object):
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.is_open = False
|
|
9
|
+
self.was_open = False
|
|
10
|
+
self.did_something = False
|
|
11
|
+
|
|
12
|
+
def open(self):
|
|
13
|
+
self.was_open = False
|
|
14
|
+
self.is_open = True
|
|
15
|
+
|
|
16
|
+
def close(self):
|
|
17
|
+
self.is_open = False
|
|
18
|
+
self.was_open = True
|
|
19
|
+
|
|
20
|
+
def __enter__(self):
|
|
21
|
+
self.open()
|
|
22
|
+
return self
|
|
23
|
+
|
|
24
|
+
def __exit__(self, *args):
|
|
25
|
+
self.close()
|
|
26
|
+
|
|
27
|
+
def do_something(self):
|
|
28
|
+
self.did_something = True
|
|
29
|
+
raise Exception()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ErrorHandlingTest(unittest.TestCase):
|
|
33
|
+
def test_throw_exception(self):
|
|
34
|
+
with self.assertRaises(Exception):
|
|
35
|
+
er.handle_error_by_throwing_exception()
|
|
36
|
+
|
|
37
|
+
def test_return_none(self):
|
|
38
|
+
self.assertEqual(er.handle_error_by_returning_none('1'), 1,
|
|
39
|
+
'Result of valid input should not be None')
|
|
40
|
+
self.assertIsNone(er.handle_error_by_returning_none('a'),
|
|
41
|
+
'Result of invalid input should be None')
|
|
42
|
+
|
|
43
|
+
def test_return_tuple(self):
|
|
44
|
+
successful_result, result = er.handle_error_by_returning_tuple('1')
|
|
45
|
+
self.assertIs(successful_result, True,
|
|
46
|
+
'Valid input should be successful')
|
|
47
|
+
self.assertEqual(result, 1, 'Result of valid input should not be None')
|
|
48
|
+
|
|
49
|
+
failure_result, result = er.handle_error_by_returning_tuple('a')
|
|
50
|
+
self.assertIs(failure_result, False,
|
|
51
|
+
'Invalid input should not be successful')
|
|
52
|
+
|
|
53
|
+
def test_filelike_objects_are_closed_on_exception(self):
|
|
54
|
+
filelike_object = FileLike()
|
|
55
|
+
with self.assertRaises(Exception):
|
|
56
|
+
er.filelike_objects_are_closed_on_exception(filelike_object)
|
|
57
|
+
self.assertIs(filelike_object.is_open, False,
|
|
58
|
+
'filelike_object should be closed')
|
|
59
|
+
self.assertIs(filelike_object.was_open, True,
|
|
60
|
+
'filelike_object should have been opened')
|
|
61
|
+
self.assertIs(filelike_object.did_something, True,
|
|
62
|
+
'filelike_object should call do_something()')
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if __name__ == '__main__':
|
|
66
|
+
unittest.main()
|