Skip to content

Commit df822dc

Browse files
authored
Merge pull request #316 from realpython/python-doctest
Sample code for the `doctest` article
2 parents c147bde + c75d891 commit df822dc

18 files changed

+457
-0
lines changed

python-doctest/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Python's doctest: Document and Test Your Code at Once
2+
3+
This folder provides the code examples for the article [Python's doctest: Document and Test Your Code at Once](https://realpython.com/python-doctest/).
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Functions to Perform Arithmetic Calculations
2+
3+
The `calculations.py` Python module provides basic arithmetic operations, including addition, subtraction, multiplication, and division.
4+
5+
Here are a few examples of how to use the functions in `calculations.py`:
6+
7+
```python
8+
>>> import calculations
9+
10+
>>> calculations.add(2, 2)
11+
4.0
12+
13+
>>> calculations.subtract(2, 2)
14+
0.0
15+
16+
>>> calculations.multiply(2, 2)
17+
4.0
18+
19+
>>> calculations.divide(2, 2)
20+
1.0
21+
22+
```
23+
24+
These examples show how to use the `calculations.py` module in your code.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""Provide several sample math calculations.
2+
3+
This module allows the user to make mathematical calculations.
4+
5+
Module-level tests:
6+
>>> add(2, 4)
7+
6.0
8+
>>> subtract(5, 3)
9+
2.0
10+
>>> multiply(2.0, 4.0)
11+
8.0
12+
>>> divide(4.0, 2)
13+
2.0
14+
"""
15+
16+
17+
def add(a, b):
18+
"""Compute and return the sum of two numbers.
19+
20+
Tests for add():
21+
>>> add(4.0, 2.0)
22+
6.0
23+
>>> add(4, 2)
24+
6.0
25+
"""
26+
return float(a + b)
27+
28+
29+
def subtract(a, b):
30+
"""Calculate the difference of two numbers.
31+
32+
Tests for subtract():
33+
>>> subtract(4.0, 2.0)
34+
2.0
35+
>>> subtract(4, 2)
36+
2.0
37+
"""
38+
return float(a - b)
39+
40+
41+
def multiply(a, b):
42+
"""Compute and return the product of two numbers.
43+
44+
Tests for multiply():
45+
>>> multiply(4.0, 2.0)
46+
8.0
47+
>>> multiply(4, 2)
48+
8.0
49+
"""
50+
return float(a * b)
51+
52+
53+
def divide(a, b):
54+
"""Compute and return the quotient of two numbers.
55+
56+
Tests for divide():
57+
>>> divide(4.0, 2.0)
58+
2.0
59+
>>> divide(4, 2)
60+
2.0
61+
>>> divide(4, 0)
62+
Traceback (most recent call last):
63+
ZeroDivisionError: division by zero
64+
"""
65+
return float(a / b)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import doctest
2+
import unittest
3+
4+
import calculations
5+
6+
7+
def load_tests(loader, tests, ignore):
8+
tests.addTests(doctest.DocFileSuite("test_calculations.txt"))
9+
tests.addTests(doctest.DocTestSuite(calculations))
10+
return tests
11+
12+
13+
# Your unittest tests goes here...
14+
15+
if __name__ == "__main__":
16+
unittest.main()
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
>>> import calculations
2+
3+
>>> calculations.add(2, 2)
4+
4.0
5+
6+
>>> calculations.subtract(2, 2)
7+
0.0
8+
9+
>>> calculations.multiply(2, 2)
10+
4.0
11+
12+
>>> calculations.divide(2, 2)
13+
1.0
14+
15+
>>> def test_add():
16+
... import calculations
17+
... return calculations.add(2, 4)
18+
>>> test_add()
19+
6.0

python-doctest/context.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
total = 100
2+
3+
4+
def decrement_by(number):
5+
"""Decrement the global total variable by a given number.
6+
7+
>>> local_total = decrement_by(50)
8+
>>> local_total
9+
50
10+
11+
Changes to total don't affect the code's global scope
12+
>>> total
13+
100
14+
"""
15+
global total
16+
total -= number
17+
return total
18+
19+
20+
def increment_by(number):
21+
"""Increment the global total variable by a given number.
22+
23+
The initial value of total's shallow copy is 50
24+
>>> increment_by(10)
25+
60
26+
27+
The local_total variable is not defined in this test
28+
>>> local_total
29+
Traceback (most recent call last):
30+
NameError: name 'local_total' is not defined
31+
"""
32+
global total
33+
total += number
34+
return total

python-doctest/failing_tests.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Sample failing tests.
2+
3+
The output must be an integer
4+
>>> 5 + 7
5+
12.0
6+
7+
The output must not contain quotes
8+
>>> print("Hello, World!")
9+
'Hello, World!'
10+
11+
The output must not use double quotes
12+
>>> "Hello," + " World!"
13+
"Hello, World!"
14+
15+
The output must not contain leading or trailing spaces
16+
>>> print("Hello, World!")
17+
Hello, World!
18+
19+
The traceback doesn't include the correct exception message
20+
>>> raise ValueError("incorrect value")
21+
Traceback (most recent call last):
22+
ValueError: invalid value
23+
"""

python-doctest/fizzbuzz.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# The commented versions of fizzbuzz() below reflect the steps
2+
# followed to get to the final version at the end of the file.
3+
4+
# Replace numbers that are divisible by 3 with "fizz"
5+
# def fizzbuzz(numbers):
6+
# """Implement the Fizz buzz game.
7+
8+
# >>> fizzbuzz([3, 6, 9, 12])
9+
# ['fizz', 'fizz', 'fizz', 'fizz']
10+
# """
11+
12+
13+
# # Replace numbers that are divisible by 3 with "fizz"
14+
# def fizzbuzz(numbers):
15+
# """Implement the Fizz buzz game.
16+
17+
# >>> fizzbuzz([3, 6, 9, 12])
18+
# ['fizz', 'fizz', 'fizz', 'fizz']
19+
# """
20+
# result = []
21+
# for number in numbers:
22+
# if number % 3 == 0:
23+
# result.append("fizz")
24+
# else:
25+
# result.append(number)
26+
# return result
27+
28+
29+
# Replace numbers that are divisible by 5 with "buzz"
30+
# def fizzbuzz(numbers):
31+
# """Implement the Fizz buzz game.
32+
33+
# >>> fizzbuzz([3, 6, 9, 12])
34+
# ['fizz', 'fizz', 'fizz', 'fizz']
35+
36+
# >>> fizzbuzz([5, 10, 20, 25])
37+
# ['buzz', 'buzz', 'buzz', 'buzz']
38+
# """
39+
# result = []
40+
# for number in numbers:
41+
# if number % 3 == 0:
42+
# result.append("fizz")
43+
# elif number % 5 == 0:
44+
# result.append("buzz")
45+
# else:
46+
# result.append(number)
47+
# return result
48+
49+
50+
# Replace numbers that are divisible by 3 and 5 with "fizz buzz"
51+
def fizzbuzz(numbers):
52+
"""Implement the Fizz buzz game.
53+
54+
>>> fizzbuzz([3, 6, 9, 12])
55+
['fizz', 'fizz', 'fizz', 'fizz']
56+
57+
>>> fizzbuzz([5, 10, 20, 25])
58+
['buzz', 'buzz', 'buzz', 'buzz']
59+
60+
>>> fizzbuzz([15, 30, 45])
61+
['fizz buzz', 'fizz buzz', 'fizz buzz']
62+
63+
>>> fizzbuzz([3, 6, 5, 10, 15, 30])
64+
['fizz', 'fizz', 'buzz', 'buzz', 'fizz buzz', 'fizz buzz']
65+
"""
66+
result = []
67+
for number in numbers:
68+
if number % 15 == 0:
69+
result.append("fizz buzz")
70+
elif number % 3 == 0:
71+
result.append("fizz")
72+
elif number % 5 == 0:
73+
result.append("buzz")
74+
else:
75+
result.append(number)
76+
return result

python-doctest/greet.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
def greet_with_bank_line(name="World"):
2+
"""Print a greeting.
3+
4+
Usage examples:
5+
>>> greet("Pythonista")
6+
Hello, Pythonista!
7+
<BLANKLINE>
8+
How have you been?
9+
"""
10+
print(f"Hello, {name}!")
11+
print()
12+
print("How have you been?")
13+
14+
15+
def greet_with_raw_docstring(name="World"):
16+
r"""Print a greeting.
17+
18+
Usage examples:
19+
>>> greet("Pythonista")
20+
/== Hello, Pythonista! ==\
21+
\== How have you been? ==/
22+
"""
23+
print(f"/== Hello, {name}! ==\\")
24+
print("\\== How have you been? ==/")
25+
26+
27+
def greet_with_scaped_backslash(name="World"):
28+
"""Print a greeting.
29+
30+
Usage examples:
31+
>>> greet("Pythonista")
32+
/== Hello, Pythonista! ==\\
33+
\\== How have you been? ==/
34+
"""
35+
print(f"/== Hello, {name}! ==\\")
36+
print("\\== How have you been? ==/")

python-doctest/identity.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
def get_id(obj):
2+
"""Return the identity of an object.
3+
4+
This test always fails
5+
>>> get_id(1) # doctest: +ELLIPSIS
6+
...
7+
"""
8+
return id(obj)

0 commit comments

Comments
 (0)