trackler 2.2.1.52 → 2.2.1.53
Sign up to get free protection for your applications and to get access to all the features.
- 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()
|