|
1 | 1 | --- |
2 | 2 | layout: page |
3 | 3 | title: Testing |
4 | | -subtitle: Running Tests with Nose |
| 4 | +subtitle: Running Tests with pytest |
5 | 5 | minutes: 10 |
6 | 6 | --- |
7 | 7 | > ## Learning Objectives {.objectives} |
8 | | -> |
9 | | -> - Understand how to run a test suite using the nose framework |
10 | | -> - Understand how to read the output of a nose test suite |
| 8 | +> |
| 9 | +> - Understand how to run a test suite using the pytest framework |
| 10 | +> - Understand how to read the output of a pytest test suite |
11 | 11 |
|
12 | 12 |
|
13 | | -We created a suite of tests for our mean function, but it was annoying to run |
| 13 | +We created a suite of tests for our mean function, but it was annoying to run |
14 | 14 | them one at a time. It would be a lot better if there were some way to run them |
15 | 15 | all at once, just reporting which tests fail and which succeed. |
16 | 16 |
|
@@ -54,71 +54,73 @@ def test_complex(): |
54 | 54 | ~~~ |
55 | 55 |
|
56 | 56 | Once these tests are written in a file called `test_mean.py`, the command |
57 | | -"nosetests" can be called from the directory containing the tests: |
| 57 | +`py.test` can be called from the directory containing the tests: |
58 | 58 |
|
59 | 59 | ~~~ {.bash} |
60 | | -$ nosetests |
| 60 | +$ py.test |
61 | 61 | ~~~ |
62 | 62 | ~~~ {.output} |
63 | | -....F |
64 | | -====================================================================== |
65 | | -FAIL: test_mean.test_complex |
66 | | ----------------------------------------------------------------------- |
67 | | -Traceback (most recent call last): |
68 | | - File "/Users/khuff/anaconda/envs/py3k/lib/python3.3/site-packages/nose/case.py", line 198, in runTest |
69 | | - self.test(*self.arg) |
70 | | - File "/Users/khuff/repos/2015-06-04-berkeley/testing/test_mean.py", line 34, in test_complex |
71 | | - assert obs == exp |
72 | | -AssertionError |
| 63 | +collected 5 items |
| 64 | +
|
| 65 | +test_mean.py ....F |
| 66 | +
|
| 67 | +================================== FAILURES =================================== |
| 68 | +________________________________ test_complex _________________________________ |
73 | 69 |
|
74 | | ----------------------------------------------------------------------- |
75 | | -Ran 5 tests in 3.746s |
| 70 | + def test_complex(): |
| 71 | + # given that complex numbers are an unordered field |
| 72 | + # the arithmetic mean of complex numbers is meaningless |
| 73 | + num_list = [2 + 3j, 3 + 4j, -32 - 2j] |
| 74 | + obs = mean(num_list) |
| 75 | + exp = NotImplemented |
| 76 | +> assert obs == exp |
| 77 | +E assert (-9+1.6666666666666667j) == NotImplemented |
76 | 78 |
|
77 | | -FAILED (failures=1) |
| 79 | +test_mean.py:34: AssertionError |
| 80 | +===================== 1 failed, 4 passed in 2.71 seconds ====================== |
78 | 81 | ~~~ |
79 | 82 |
|
80 | | -In the above case, the python nose package 'sniffed-out' the tests in the |
| 83 | +In the above case, the pytest package 'sniffed-out' the tests in the |
81 | 84 | directory and ran them together to produce a report of the sum of the files and |
82 | 85 | functions matching the regular expression `[Tt]est[-_]*`. |
83 | 86 |
|
84 | 87 |
|
85 | 88 | The major boon a testing framework provides is exactly that, a utility to find and run the |
86 | | -tests automatically. With `nose`, this is the command-line tool called |
87 | | -_nosetests_. When _nosetests_ is run, it will search all the directories whose names start or |
88 | | -end with the word _test_, find all of the Python modules in these directories |
89 | | -whose names |
90 | | -start or end with _test_, import them, and run all of the functions and classes |
91 | | -whose names start or end with _test_. In fact, `nose` looks for any names |
92 | | -that match the regular expression `'(?:^|[\\b_\\.-])[Tt]est'`. |
| 89 | +tests automatically. With pytest, this is the command-line tool called |
| 90 | +`py.test`. When `py.test` is run, it will search all directories below where it was called, |
| 91 | +find all of the Python files in these directories whose names |
| 92 | +start or end with `test`, import them, and run all of the functions and classes |
| 93 | +whose names start with `test` or `Test`. |
93 | 94 | This automatic registration of test code saves tons of human time and allows us to |
94 | 95 | focus on what is important: writing more tests. |
95 | 96 |
|
96 | | -When you run _nosetests_, it will print a dot (`.`) on the screen for every test |
| 97 | +When you run `py.test`, it will print a dot (`.`) on the screen for every test |
97 | 98 | that passes, |
98 | | -an `F` for every test that fails, and an `E` for every test were there was an |
99 | | -unexpected error. In rarer situations you may also see an `S` indicating a |
100 | | -skipped tests (because the test is not applicable on your system) or a `K` for a known |
101 | | -failure (because the developers could not fix it promptly). After the dots, _nosetests_ |
102 | | -will print summary information. |
| 99 | +an `F` for every test that fails or where there was an unexpected error. |
| 100 | +In rarer situations you may also see an `s` indicating a |
| 101 | +skipped tests (because the test is not applicable on your system) or a `x` for a known |
| 102 | +failure (because the developers could not fix it promptly). After the dots, pytest |
| 103 | +will print summary information. |
103 | 104 |
|
104 | 105 |
|
105 | 106 | > ## Fix The Failing Code {.challenge} |
106 | 107 | > |
107 | | -> Without changing the tests, alter the mean.py file from the previous section until it passes. |
108 | | -> When it passes, _nosetests_ will produce results like the following: |
| 108 | +> Without changing the tests, alter the mean.py file from the previous section until it passes. |
| 109 | +> When it passes, `py.test` will produce results like the following: |
109 | 110 | > |
110 | 111 | > ~~~ {.bash} |
111 | | -> $ nosetests |
| 112 | +> $ py.test |
112 | 113 | > ~~~ |
113 | 114 | > ~~~ {.output} |
114 | | -> ..... |
115 | | -> |
116 | | -> Ran 5 tests in 3.746s |
| 115 | +> collected 5 items |
117 | 116 | > |
118 | | -> OK |
119 | | -> ~~~ |
| 117 | +> test_mean.py ..... |
| 118 | +> |
| 119 | +> ========================== 5 passed in 2.68 seconds =========================== |
120 | 120 |
|
121 | | -As we write more code, we would write more tests, and _nosetests_ would produce |
| 121 | +As we write more code, we would write more tests, and pytest would produce |
122 | 122 | more dots. Each passing test is a small, satisfying reward for having written |
123 | 123 | quality scientific software. Now that you know how to write tests, let's go |
124 | 124 | into what can go wrong. |
| 125 | +
|
| 126 | +
|
0 commit comments