PyTest¶
Contents¶
Indices and tables¶
Exercise¶
For this week, the goal is to practice TDD by writing a small python program while simultaneously writing tests (using PyTest) for that program. This program will be expanded next week to include the addition of mocks.
Following the practice of TDD, you should:
- First, write a failing test that is some atomic action you want to the program to perform.
- Write the simplest bit of code to make the test pass.
- Repeat steps 1 and 2 until the program is complete.
While not required, it is highly encouraged that you use PyCharm for this activity, as the built in support for pytest makes the process much easier.
The sample program is based on the Casino game craps and should support the following rule set:
- An initial roll of two dice occurs.
- If the total is 7 or 11, the program should return 1, indicating a win.
- If the total is 2, 3, or 12, the program should return 0, indicating a loss.
- Otherwise, continue to roll two dice until either:
- The roll total is 7. The program should return 0, indicating a loss.
- The roll total is equal to the inital roll. The program should return 1, indicating a win.
On completion of this exercise, you should have a program that satisfies the above and tests to verify correct program operation.
Hints¶
Here is a recommended set of atomic steps that could be used to incrementally build your program via the TDD methodology:
- Create a helper routine called roll_dice (fill it with just a pass statement for now; no code should be written yet).
- Write a test to examine the function output and verify it falls between 1 and 6. Use parametrization to repeat this for a large sample set.
- Write the simplest code possible to make this test pass.
- Write a test to show that the randomness of the roll is fair by rolling a very large sample set of dice and showing the average converges to 3.5 within an acceptable tolerance.
- Write the code necessary to make this test pass.
- Create a helper routine called play_craps that takes an integer input (fill it with just a pass statement) for now.
- Write a test to verify that if the input is 7 or 11, the function returns 1.
- Write the simplest and smallest amount of code to make this test pass.
- Write a test to verify that if the input is 2, 3, or 12, the function returns 0.
- Write the simplest and smallest amount of code to make this test pass.
- Write a test to verify that if the input is 4, 5, 6, 8, 9, or 10, the program returns -1 (this will later be properly tested once the concept of mocking is introduced).
Hints¶
- Tests can be run n number of times using the following syntax:
@pytest.mark.parametrize('num', range(0, n))
def test_foo(num):
pass
This effectively passes the value of num through the range 0..n-1. The test does not use the parameter, so this just results in multiple executions.
- The “simplest” code can often be even more simple than you think. For example, in 2b above, returning a constant value between 1 and 6 is an acceptable solution for that atomic piece.
- In 1c, rather than using parametrization to run the test multiple times, simply run a single test with multiple calls to roll_dice in a loop. Capture the output and average it.
Solution¶
When you are ready to see one potential solution, you can examine the supplied
PyCharm project
.