kopia lustrzana https://github.com/micropython/micropython-lib
215 wiersze
6.7 KiB
Python
215 wiersze
6.7 KiB
Python
"""Tests using unittest.subtest as an example reference for how it is used"""
|
|
|
|
import unittest
|
|
|
|
|
|
def factorial(value: int) -> int:
|
|
"""Iterative factorial algorithm implementation"""
|
|
result = 1
|
|
|
|
for i in range(1, value + 1):
|
|
result *= i
|
|
|
|
return result
|
|
|
|
|
|
class Person:
|
|
"""Represents a person with a name, age, and who can make friends"""
|
|
|
|
def __init__(self, name: str, age: int) -> None:
|
|
self.name = name
|
|
self.age = age
|
|
self.friends = set()
|
|
|
|
def __repr__(self) -> str:
|
|
return f"Person({self.name})"
|
|
|
|
def add_friend(self, friend):
|
|
"""Logs that this Person has made a new friend"""
|
|
self.friends.add(friend)
|
|
|
|
def has_friend(self, friend_candidate) -> bool:
|
|
"""Determines if this Person has the friend `friend_candidate`"""
|
|
return friend_candidate in self.friends
|
|
|
|
def is_oldest_friend(self) -> bool:
|
|
"""Determines whether this Person is the oldest out of themself and their friends"""
|
|
return self.age > max(friend.age for friend in self.friends)
|
|
|
|
|
|
class TestSubtest(unittest.TestCase):
|
|
"""Examples/tests of unittest.subTest()"""
|
|
|
|
def test_sorted(self) -> None:
|
|
"""Test that the selection sort function correctly sorts lists"""
|
|
tests = [
|
|
{
|
|
"unsorted": [-68, 15, 52, -54, -64, 20, 2, 66, 33],
|
|
"sorted": [-68, -64, -54, 2, 15, 20, 33, 52, 66],
|
|
"correct": True,
|
|
},
|
|
{
|
|
"unsorted": [-68, 15, 52, -54, -64, 20, 2, 66, 33],
|
|
"sorted": [-68, -54, -64, 2, 15, 20, 33, 52, 66],
|
|
"correct": False,
|
|
},
|
|
{
|
|
"unsorted": [-68, 15, 52, 54, -64, 20, 2, 66, 33],
|
|
"sorted": [-68, -64, -54, 2, 15, 20, 33, 52, 66],
|
|
"correct": False,
|
|
},
|
|
{
|
|
"unsorted": [],
|
|
"sorted": [],
|
|
"correct": True,
|
|
},
|
|
{
|
|
"unsorted": [42],
|
|
"sorted": [42],
|
|
"correct": True,
|
|
},
|
|
{
|
|
"unsorted": [42],
|
|
"sorted": [],
|
|
"correct": False,
|
|
},
|
|
{
|
|
"unsorted": [],
|
|
"sorted": [24],
|
|
"correct": False,
|
|
},
|
|
{
|
|
"unsorted": [43, 44],
|
|
"sorted": [43, 44],
|
|
"correct": True,
|
|
},
|
|
{
|
|
"unsorted": [44, 43],
|
|
"sorted": [43, 44],
|
|
"correct": True,
|
|
},
|
|
]
|
|
|
|
for test in tests:
|
|
with self.subTest(): # Subtests continue to be tested, even if an earlier one fails
|
|
if test["correct"]: # Tests that match what is expected
|
|
self.assertEqual(sorted(test["unsorted"]), test["sorted"])
|
|
else: # Tests that are meant to fail
|
|
with self.assertRaises(AssertionError):
|
|
self.assertEqual(sorted(test["unsorted"]), test["sorted"])
|
|
|
|
def test_factorial(self) -> None:
|
|
"""Test that the factorial fuction correctly calculates factorials
|
|
|
|
Makes use of `msg` argument in subtest method to clarify which subtests had an
|
|
error in the results
|
|
"""
|
|
tests = [
|
|
{
|
|
"operand": 0,
|
|
"result": 1,
|
|
"correct": True,
|
|
},
|
|
{
|
|
"operand": 1,
|
|
"result": 1,
|
|
"correct": True,
|
|
},
|
|
{
|
|
"operand": 1,
|
|
"result": 0,
|
|
"correct": False,
|
|
},
|
|
{
|
|
"operand": 2,
|
|
"result": 2,
|
|
"correct": True,
|
|
},
|
|
{
|
|
"operand": 3,
|
|
"result": 6,
|
|
"correct": True,
|
|
},
|
|
{
|
|
"operand": 3,
|
|
"result": -6,
|
|
"correct": False,
|
|
},
|
|
{
|
|
"operand": 4,
|
|
"result": 24,
|
|
"correct": True,
|
|
},
|
|
{
|
|
"operand": 15,
|
|
"result": 1_307_674_368_000,
|
|
"correct": True,
|
|
},
|
|
{
|
|
"operand": 15,
|
|
"result": 1_307_674_368_001,
|
|
"correct": False,
|
|
},
|
|
{
|
|
"operand": 11,
|
|
"result": 39_916_800,
|
|
"correct": True,
|
|
},
|
|
]
|
|
|
|
for test in tests:
|
|
with self.subTest(
|
|
f"{test['operand']}!"
|
|
): # Let's us know we were testing "x!" when we get an error
|
|
if test["correct"]:
|
|
self.assertEqual(factorial(test["operand"]), test["result"])
|
|
else:
|
|
with self.assertRaises(AssertionError):
|
|
self.assertEqual(factorial(test["operand"]), test["result"])
|
|
|
|
def test_person(self) -> None:
|
|
"""Test the Person class and its friend-making ability
|
|
|
|
Makes use of subtest's params to specify relevant data about the tests, which is
|
|
helpful for debugging
|
|
"""
|
|
# Create a friendship
|
|
alice = Person("Alice", 22)
|
|
bob = Person("Bob", 23)
|
|
alice.add_friend(bob)
|
|
|
|
# Test friendship init
|
|
with self.subTest(
|
|
"Alice should have Bob as a friend", name=alice.name, friends=bob.friends
|
|
): # Params `name` and `friends` provide useful data for debugging purposes
|
|
self.assertTrue(alice.has_friend(bob))
|
|
|
|
with self.subTest(
|
|
"Bob should not have Alice as a friend", name=bob.name, friends=bob.friends
|
|
):
|
|
self.assertFalse(bob.has_friend(alice))
|
|
|
|
# Friendship is not always commutative, so Bob is not implicitly friends with Alice
|
|
with self.subTest("Alice and Bob should not both be friends with eachother"):
|
|
with self.assertRaises(AssertionError):
|
|
self.assertTrue(bob.has_friend(alice) and alice.has_friend(bob))
|
|
|
|
# Bob becomes friends with Alice
|
|
bob.add_friend(alice)
|
|
|
|
with self.subTest(
|
|
"Bob should now have Alice as a friend", name=bob.name, friends=bob.friends
|
|
):
|
|
self.assertTrue(bob.has_friend(alice))
|
|
|
|
with self.subTest(
|
|
"Bob should be the oldest of his friends",
|
|
age=bob.age,
|
|
friend_ages=[friend.age for friend in bob.friends],
|
|
): # Different params can be used for different subtests in the same test
|
|
self.assertTrue(bob.is_oldest_friend())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|