Rozdział 23 · Część V · Sprawdzamy i automatyzujemy

Sprawdzamy wyszukiwanie duplikatów

Puste pliki i wielomegabajtowy plik sprawdzają dwa przypadki, które łatwo przeoczyć w zwykłym teście.

SafeSort · Część 5 z 6Testy i CI
Arrangedwa pliki ztej samej treściActfind_duplicates()Assertjedną grupę dwóchakta

Testy dla find_duplicates() nie tylko „typowe”

tests/test_duplicates.py
def test_identical_content_files_are_grouped(tmp_path):
    a = tmp_path / "notes.txt"
    b = tmp_path / "copy_of_notes.txt"
    a.write_text(„ten sam tekst”)
    b.write_text(„ten sam tekst”)

    groups = find_duplicates(scan(tmp_path, Config()))

    assert len(groups) == 1
    assert len(groups[0].files) == 2

def test_empty_files_are_duplicates_of_each_other(tmp_path):
    (tmp_path / "a.txt").write_text("")
    (tmp_path / "b.txt").write_text("")

    groups = find_duplicates(scan(tmp_path, Config()))

    assert len(groups) == 1
    assert groups[0].size == 0
Wynik i sposób czytania są sprawdzane osobno
plik większy niż jeden blok i poprawny digest jedynie dowodzą wyniku funkcji. Taki test nie obserwuje wywołań read(): Implementacja mogłaby odczytać cały plik naraz i nadal zwracać ten sam SHA-256. bounded reads kontraktu jest sprawdzany przez osobny instrumented reader.
tests/test_duplicates.py
def test_sha256_large_file_has_correct_result(tmp_path):
    data = b"x" * (5 * 1024 * 1024)  # 5 MB — więcej niż jeden blok odczytu
    path = tmp_path / "bolshoj_fajl.bin"
    path.write_bytes(data)

    assert sha256_file(path) == hashlib.sha256(data).hexdigest()
tests/test_duplicates.py: interaction test
class RecordingReader(io.BytesIO):
    def __init__(self, data: bytes) -> None:
        super().__init__(data)
        self.requested_sizes = []

    def read(self, size: int = -1) -> bytes:
        self.requested_sizes.append(size)
        return super().read(size)

def test_sha256_stream_uses_multiple_bounded_reads():
    reader = RecordingReader(b"abcdefghij")

    digest = sha256_stream(reader, chunk_size=4)

    assert digest == hashlib.sha256(b"abcdefghij").hexdigest()
    assert reader.requested_sizes == [4, 4, 4, 4]
    assert max(reader.requested_sizes) == 4

Pierwszym testem jest result test (black-box): sprawdza, co wróciło. Drugi sprawdza interaction/implementation contract: zależność otrzymała kilka ograniczonych read(4). Mały strumień nagrania Jest to obserwowane bez silnej infrastruktury mocking-.

Praktyka: Testy plików duplikatów i pustych
Interaktywny Laptop w przeglądarce: Python 3.14 przez Pyodide, bez instalacji
Otwórz praktykę →
Oficjalna dokumentacja
pytest — How to write and report assertions
unittest.mock — mock object library