Zanurkuj w Pythonie/Programowanie funkcyjne
Nurkujemy
[edytuj]W rozdziale 13 ("Testowanie") poznaliście filozofię testowania jednostkowego. Rozdział 14 ("Testowanie 2") pozwolił wam zaimplementować podstawowe testy jednostkowe w języku Python. Rozdział 15 ("Refaktoryzacja") uświadomił wam, że dzięki testom jednostkowym refaktoryzacja na wielką skalę staje się znacznie prostsza. W tym zaś rozdziale, choć wciąż będziemy bazować na wcześniejszych, przykładowych programach, skupimy się bardziej na zaawansowanych technikach stosowanych w języku Python, niż na samym testowaniu.
Poniżej przedstawiony jest pełny kod programu będącego tanim i prostym sposobem uruchamiania testów regresyjnych. Pobiera on testy jednostkowe, jakie zostały napisane dla poszczególnych modułów, zbiera je do jednego, wielkiego zestawu testowego i uruchamia je wszystkie jako całość. Obecnie, podczas pisania tej książki, skrypt ten służy mi jako część procesu budowania; napisałem testy jednostkowe dla wielu przykładowych programów (nie tylko dla roman.py przedstawionego w rozdziale 13, "Testowanie"), a pierwszą rzeczą jaką robi skrypt do automatycznego budowania jest uruchomienie tego właśnie programu, dzięki czemu mogę się upewnić, że wszystkie moje przykłady wciąż działają. Jeśli zakończy się on niepowodzeniem, wówczas automatyczne budowanie zostaje natychmiast przerwane. Nie chcę publikować niedziałających przykładów, podobnie jak wy nie chcecie pobierać ich z sieci, a później długo siedzieć, drapać się po głowie i zastanawiać, dlaczego nie działają.
Przykład 16.1. regression.py
Jeśli jeszcze tego nie zrobiliście, możecie pobrać ten oraz inne przykłady używane w tej książce.
"""Regression testing framework
This module will search for scripts in the same directory named
XYZtest.py. Each such script should be a test suite that tests a
module through PyUnit. (As of Python 2.1, PyUnit is included in
the standard library as "unittest".) This script will aggregate all
found test suites into one big test suite and run them all at once.
"""
import sys, os, re, unittest
def regressionTest():
path = os.path.abspath(os.path.dirname(sys.argv[0]))
files = os.listdir(path)
test = re.compile("test\.py$", re.IGNORECASE)
files = filter(test.search, files)
filenameToModuleName = lambda f: os.path.splitext(f)[0]
moduleNames = map(filenameToModuleName, files)
modules = map(__import__, moduleNames)
load = unittest.defaultTestLoader.loadTestsFromModule
return unittest.TestSuite(map(load, modules))
if __name__ == "__main__":
unittest.main(defaultTest="regressionTest")
Uruchomienie programu w tym samym katalogu, w którym znajdują się pozostałe przykładowe skrypty używane w tej książce, spowoduje wyszukanie wszystkich testów jednostkowych o nazwie moduletest.py, uruchomienie ich wszystkich jako jeden test, a następnie stwierdzenie, czy jako całość przeszły, czy nie.
Przykład 16.2. Przykładowe wyjście z programu regression.py
[you@localhost py]$ python regression.py -v help should fail with no object ... ok #(1) help should return known result for apihelper ... ok help should honor collapse argument ... ok help should honor spacing argument ... ok buildConnectionString should fail with list input ... ok #(2) buildConnectionString should fail with string input ... ok buildConnectionString should fail with tuple input ... ok buildConnectionString handles empty dictionary ... ok buildConnectionString returns known result with known input ... ok fromRoman should only accept uppercase input ... ok #(3) toRoman should always return uppercase ... ok fromRoman should fail with blank string ... ok fromRoman should fail with malformed antecedents ... ok fromRoman should fail with repeated pairs of numerals ... ok fromRoman should fail with too many repeated numerals ... ok fromRoman should give known result with known input ... ok toRoman should give known result with known input ... ok fromRoman(toRoman(n))==n for all n ... ok toRoman should fail with non-integer input ... ok toRoman should fail with negative input ... ok toRoman should fail with large input ... ok toRoman should fail with 0 input ... ok kgp a ref test ... ok kgp b ref test ... ok kgp c ref test ... ok kgp d ref test ... ok kgp e ref test ... ok kgp f ref test ... ok kgp g ref test ... ok ---------------------------------------------------------------------- Ran 29 tests in 2.799s OK
- Pierwszych 5 testów pochodzi z apihelpertest.py, który testuje przykładowy skrypt z rozdziału 4 (Potęga introspekcji).
- Kolejne 5 testów pochodzi z odbchelpertest.py, który testuje przykładowy skrypt z rozdziału 2 (Pierwszy program)
- Pozostałe testy pochodzą z romantest.py, zestawu testów, który zgłębialiśmy w rozdziale 13, ("Testowanie").