Moduły programistyczne

https://docs.python.org/3/library/doctest.html

WPROWADZENIE

Podstawowym sposobem umieszczania kodu samosprawdzającego moduł Pythona jest wykorzystanie zmiennej __name__. Bardziej zaawansowane narzędzia testujące oferują moduły doctest i unittest z biblioteki standardowej. Moduł unittest2 to backport nowych możliwości z Pythona 2.7 do Pythona 2.4-2.6. Moduły nose i pytest to dodatkowe narzędzia do pisania testów z lekką składnią.

MODUŁ doctest


def average(values):
    """Oblicza średnią arytmetyczną listy liczb.
    >>> average([20, 30, 70])
    40.0
    """
    return sum(values, 0.0) / len(values)

if __name__ == "__main__":
    import doctest
    doctest.testmod()   # automatyczne sprawdzanie wbudowanych testów

# Sprawdzanie przykładów podanych w pliku tekstowym.
# Zawartość pliku jet traktowana jako jeden wielki docstring.

import doctest
doctest.testfile("example.txt")

MODUŁ pytest

Moduł 'pytest' należy do biblioteki standardowej od Pythona 3.6.


# Przykładowy plik z testami test_sample.py ('test' w nazwie pliku).

def inc(x):
    return x + 1

def test_answer():   # 'test' w nazwie funkcji
    assert inc(3) == 5   # intentional error, 'assert' is used

# Testy uruchamiamy w powłoce systemu operacyjnego poleceniem 'pytest',
# tak działa 'discovery mode'.

MODUŁ timeit

Moduł służy do testowania czasu wykonania małych kawałków kodu. Do testowania większych bloków kodu: profile, pstats.

Głównym elementem modułu jest klasa Timer(stmt="pass", setup="pass").
Metoda repeat(self, repeat=3, number=1000000) - wywołanie timeit() kilka razy (zwraca listę wyników).
Metoda timeit(self, number=1000000) - najpierw następuje pojedyncze wykonanie poleceń z setup, a potem number wykonań stmt.


import timeit
# help(timeit)

# Często przydaje się średnik do rozdzielania poleceń.
t1 = timeit.Timer(stmt="t=a ; a=b ; b=t", setup="a=1 ; b=2")
t2 = timeit.Timer(stmt="(a,b) = (b,a)", setup="a=1 ; b=2")
print(t1.timeit())         # domyślnie milion wykonań
print(t2.timeit())
print(t2.repeat(5))        # zwraca listę 5 wyników
print(min(t2.repeat(10)))  # to jest zwykle miarodajne, a nie średnia

import timeit

# Można budować polecenia wielowierszowe.
s = """\
pierwszy wiersz
drugi wiersz
"""
t = timeit.Timer(stmt=s)
print(t.timeit())

import random
import timeit

def mysort(L, left, right):
    L[left: right+1] = sorted(L[left: right+1])

lista = list(range(1000))
random.shuffle(lista)

t1 = timeit.Timer(stmt="mysort(lista, 0, len(lista)-1)", 
                  setup="from __main__ import mysort, lista")

print(t1.timeit(1))        # pojedyncze wykonanie

# Od Pythona 2.6 można przekazywać obiekty callable bez argumentów.

import random
import timeit

def mysort(L, left, right):
    L[left: right+1] = sorted(L[left: right+1])

lista = list(range(1000))
random.shuffle(lista)

t1 = timeit.Timer(lambda: mysort(lista, 0, len(lista)-1))

print(t1.timeit(1))        # pojedyncze wykonanie

MODUŁ enum

Typ Enum został dodany do Pythona 3.4 (PEP 0435 -- Adding an Enum type to the Python standard library).


from enum import Enum
# from enum import IntEnum   # można porównywać z int

class Color(Enum):
    red = 1
    green = 2
    blue = 3

for c in Color:
    print(c)
# Color.red
# Color.green
# Color.blue