|
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