feat: 新增技能扩展N11一章相关示例源码
This commit is contained in:
79
code/newsletter/N11/tests/conftest.py
Normal file
79
code/newsletter/N11/tests/conftest.py
Normal file
@@ -0,0 +1,79 @@
|
||||
import dataclasses
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Connection:
|
||||
def execute(self, sql: str):
|
||||
print(f"execute {sql}...")
|
||||
return True
|
||||
|
||||
def close(self):
|
||||
print(f"\ndisconnect {repr(self)} object...")
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Database:
|
||||
dialect: str = "sqlite"
|
||||
|
||||
def connect(self):
|
||||
return Connection()
|
||||
|
||||
def close(self):
|
||||
print(f"\ndisconnect {repr(self)} object...")
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def sqlite():
|
||||
db = Database()
|
||||
conn = db.connect()
|
||||
try:
|
||||
yield conn
|
||||
finally:
|
||||
conn.close()
|
||||
db.close()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def mysql():
|
||||
db = Database(dialect="mysql")
|
||||
conn = db.connect()
|
||||
try:
|
||||
yield conn
|
||||
finally:
|
||||
conn.close()
|
||||
db.close()
|
||||
|
||||
|
||||
@pytest.fixture(params=["sqlite", "mysql"])
|
||||
def database(request):
|
||||
db = Database(dialect=request.param)
|
||||
conn = db.connect()
|
||||
try:
|
||||
yield conn
|
||||
finally:
|
||||
conn.close()
|
||||
db.close()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def gender():
|
||||
return ["male", "female"]
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def cpu():
|
||||
return "cpu"
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def device(cpu):
|
||||
return f"the device with {cpu}"
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def logger():
|
||||
print("\nstart recording...")
|
||||
yield
|
||||
print("\nend recording...")
|
||||
37
code/newsletter/N11/tests/pytest_setup_teardown.py
Normal file
37
code/newsletter/N11/tests/pytest_setup_teardown.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def setup_module():
|
||||
print("[module level]: setup")
|
||||
|
||||
|
||||
def teardown_module():
|
||||
print("[module level]: teardown")
|
||||
|
||||
|
||||
class TestFoo:
|
||||
def setup(self, method) -> None:
|
||||
print("\t\t[function level]: setup")
|
||||
|
||||
def teardown(self, method) -> None:
|
||||
print("\t\t[function level]: teardown")
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
print("\t[class level]: setup")
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
print("\t[class level]: teardown")
|
||||
|
||||
def test_case1(self):
|
||||
print("\t\t\t--> test case 1 here")
|
||||
assert True
|
||||
|
||||
def test_case2(self):
|
||||
print("\t\t\t--> test case 2 here")
|
||||
assert True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pytest.main([__file__, "-s", "--no-header"])
|
||||
27
code/newsletter/N11/tests/test_accumulate.py
Normal file
27
code/newsletter/N11/tests/test_accumulate.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from typing import Tuple, TypeVar
|
||||
|
||||
import pytest
|
||||
|
||||
Number = TypeVar("Number", int, float)
|
||||
|
||||
|
||||
def accumulate(*numbers: Tuple[Number]) -> Number:
|
||||
result = 0
|
||||
for n in numbers:
|
||||
if not isinstance(n, (int, float)):
|
||||
raise ValueError(f"{n} isn't a valid number value")
|
||||
|
||||
result += n
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def test_accumulate():
|
||||
numbers = [1, 2, 3, 4]
|
||||
expected = 10
|
||||
|
||||
assert accumulate(*numbers) == expected
|
||||
|
||||
|
||||
if __name__== '__main__':
|
||||
pytest.main()
|
||||
52
code/newsletter/N11/tests/test_accumulate_with_other_mark.py
Normal file
52
code/newsletter/N11/tests/test_accumulate_with_other_mark.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import sys
|
||||
from typing import Tuple, TypeVar
|
||||
|
||||
import pytest
|
||||
|
||||
Number = TypeVar("Number", int, float)
|
||||
VERSION = "0.0.2"
|
||||
|
||||
|
||||
def accumulate(*numbers: Tuple[Number]) -> Number:
|
||||
result = 0
|
||||
for n in numbers:
|
||||
if not isinstance(n, (int, float)):
|
||||
raise ValueError(f"{n} isn't a valid number value")
|
||||
|
||||
result += n
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@pytest.mark.xfail()
|
||||
@pytest.mark.parametrize("numbers, expected", argvalues=[([10, 11, -11, -12], 1)])
|
||||
def test_accumulate_with_failed(numbers, expected):
|
||||
assert accumulate(*numbers) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"numbers, expected",
|
||||
argvalues=[
|
||||
pytest.param(
|
||||
[10, 11, -11, -12], 1, marks=pytest.mark.xfail(reason="expected failed")
|
||||
)
|
||||
],
|
||||
)
|
||||
def test_accumulate_with_failed_mark(numbers, expected):
|
||||
assert accumulate(*numbers) == expected
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="the case is WIP")
|
||||
def test_wip_with_skip_mark():
|
||||
...
|
||||
|
||||
|
||||
def test_wip_with_skip_function():
|
||||
if VERSION <= '0.0.2':
|
||||
pytest.skip("the API is still on WIP")
|
||||
assert False
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform != "linux", reason="only for linux")
|
||||
def test_wip_function_only_for_linux():
|
||||
assert True
|
||||
@@ -0,0 +1,56 @@
|
||||
from typing import Tuple, TypeVar
|
||||
|
||||
import pytest
|
||||
|
||||
Number = TypeVar("Number", int, float)
|
||||
|
||||
|
||||
def accumulate(*numbers: Tuple[Number]) -> Number:
|
||||
result = 0
|
||||
for n in numbers:
|
||||
if not isinstance(n, (int, float)):
|
||||
raise ValueError(f"{n} isn't a valid number value")
|
||||
|
||||
result += n
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def test_accumulate_without_mark():
|
||||
numbers = [
|
||||
[1, 2, 3, 4],
|
||||
[5, 6, 7, 8],
|
||||
[-1, 0, 1, 0],
|
||||
[10, 11, -11, -12],
|
||||
]
|
||||
expected = (10, 26, 0, 1)
|
||||
|
||||
for number, expect in zip(numbers, expected):
|
||||
assert accumulate(*number) == expect
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
argnames="numbers,expected",
|
||||
argvalues=[
|
||||
([1, 2, 3, 4], 10),
|
||||
([5, 6, 7, 8], 26),
|
||||
([-1, 0, 1, 0], 0),
|
||||
([10, 11, -11, -12], 1),
|
||||
],
|
||||
ids=list("abcd"),
|
||||
)
|
||||
def test_accumulate_with_parametrize_mark(numbers, expected):
|
||||
assert accumulate(*numbers) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(argnames="even_number", argvalues=[2, 4])
|
||||
@pytest.mark.parametrize(argnames="odd_number", argvalues=[1, 3])
|
||||
def test_accumulate_with_multiple_parametrize_mark(even_number, odd_number):
|
||||
expected = {
|
||||
"1+2": 3,
|
||||
"1+4": 5,
|
||||
"3+2": 5,
|
||||
"3+4": 7,
|
||||
}
|
||||
expr = f"{odd_number}+{even_number}"
|
||||
assert accumulate(odd_number, even_number) == expected[expr]
|
||||
68
code/newsletter/N11/tests/test_with_fixture.py
Normal file
68
code/newsletter/N11/tests/test_with_fixture.py
Normal file
@@ -0,0 +1,68 @@
|
||||
def test_sql_with_mock_sqlite_database(sqlite):
|
||||
ok = sqlite.execute("SELECT 1;")
|
||||
assert ok
|
||||
|
||||
|
||||
def test_sql_with_mock_mysql_database(mysql):
|
||||
ok = mysql.execute("SELECT * FROM mock_table;")
|
||||
assert ok
|
||||
|
||||
|
||||
def test_gender_fixture(gender):
|
||||
print(f"Gender fixture value: {gender}")
|
||||
assert ["male", "female"] == gender
|
||||
|
||||
|
||||
class TestClassScopeFixture:
|
||||
def test_foo(self, logger):
|
||||
assert True
|
||||
|
||||
def test_bar(self, logger):
|
||||
assert True
|
||||
|
||||
|
||||
class TestClassScopeFixture2:
|
||||
def test_foo2(self, logger):
|
||||
assert True
|
||||
|
||||
def test_bar2(self, logger):
|
||||
assert True
|
||||
|
||||
|
||||
def test_with_mock_database(database):
|
||||
sql = "SELECT * FROM mock_table;"
|
||||
ok = database.execute(sql)
|
||||
assert ok
|
||||
|
||||
|
||||
def test_with_request_fixture(request):
|
||||
from pprint import pformat
|
||||
|
||||
props = [prop for prop in dir(request) if not prop.startswith("_")]
|
||||
|
||||
print(f"request properties:\n{pformat(props)}")
|
||||
assert True
|
||||
|
||||
|
||||
def test_with_capsys_fixture(capsys):
|
||||
def greet(name: str = ""):
|
||||
msg = name or "World"
|
||||
print(f"Hello, {msg}")
|
||||
|
||||
greet()
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "Hello, World\n"
|
||||
|
||||
greet("100gle")
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == "Hello, 100gle\n"
|
||||
|
||||
|
||||
def test_with_tmp_path_fixture(tmp_path):
|
||||
import pathlib
|
||||
|
||||
p = tmp_path.joinpath("foo")
|
||||
print(f"\n{p}")
|
||||
|
||||
assert isinstance(p, pathlib.Path)
|
||||
assert p.stem == "foo"
|
||||
37
code/newsletter/N11/tests/unittest_setup_teardown.py
Normal file
37
code/newsletter/N11/tests/unittest_setup_teardown.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import unittest
|
||||
|
||||
|
||||
def setUpModule():
|
||||
print("[module level]: setup")
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
print("[module level]: teardown")
|
||||
|
||||
|
||||
class TestFoo(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
print("\t\t[function level]: setup")
|
||||
|
||||
def tearDown(self) -> None:
|
||||
print("\t\t[function level]: teardown")
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
print("\t[class level]: setup")
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
print("\t[class level]: teardown")
|
||||
|
||||
def test_case1(self):
|
||||
print("\t\t\t--> test case 1 here")
|
||||
self.assertEqual(1, 1)
|
||||
|
||||
def test_case2(self):
|
||||
print("\t\t\t--> test case 2 here")
|
||||
self.assertEqual(1, 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user