04. Автоматизирано тестване
11 март 2013
За кои от типовете колекции има литерален синтаксис?
list, tuple, dict, set
На какви условия трябва да отговаря обект, за да бъде обхождан от for?
трябва да има __iter__
върнатото от __iter__ трябва да има __next__
Каква е разликата между lazy и eager изчисляването (в контекста на колекциите)?
eager върши всичко в началото и [обикновено] връща списък
lazy върши по малко работа на всяка стъпка от обхождането
Избройте поне 3 вградени функции (или типа), които връщат "мързеливи" колекции.
map
filter
range
dir(itertools)
Как можем да напишем filter чрез list comprehension-и.
lambda func, iterable: [x for x in iterable if func(x)]
Disclaimer
Днес няма да си говорим за acceptance testing, quality assurance или нещо, което се прави от "по-низшия" отдел във фирмата. Всичко тук е дело на програмиста.
Митът
Проектът идва с готово, подробно задание.
Прави се дизайн.
С него работата се разбива на малки задачи.
Те се извършват последователно.
За всяка от тях пишете кода и приключвате.
Изискванията не се променят, нито се добавя нова функционалност.
Митът v1.1
Щом съм написал един код, значи ми остава единствено да го разцъкам - няколко print-а, малко пробване в main метода/функцията и толкова.
Така или иначе няма да се променя.
А ако (не дай си боже) това се случи - аз съм го писал, знам го, няма как да допусна грешка.
Най-много да го поразцъкам още малко.
Тежката действителност
- Заданията винаги се променят.
- Често се налага един код да се преработва.
- Писането на код е сложна задача - допускат се грешки.
- Програмистите са хора - допускат грешки.
- Промяната на модул в единия край на системата като нищо може да счупи модул в другия край на системата.
- Идва по-добра идея за реализация на кода
Искаме да автоматизираме нещата
- За всичко съмнително ще пишем сценарий, който да "цъка".
- Всеки сценарий ще изпълнява кода и ще прави няколко твърдения за резултатите.
- Сценариите ще бъдат обединени в групи.
- Пускате всички тестове с едно бутонче.
- Резултатът е "Всичко мина успешно" или "Твърдения X, Y и Z в сценарии A, B и C се оказаха неверни".
unittest.TestCase
Всички методи имат опционален последен аргумент msg - текстово съобщение, което ще се покаже ако теста пропадне.
- assertTrue(expression)
- assertFalse(expression)
- assertEqual(expected, actual)
- assertNotEqual(expected, actual)
- assertIs(expected, actual)
- assertIsNot(expected, actual)
- assertIsNone(expression)
- assertIsNotNone(expression)
- assertIn(element, collection)
- assertNotIn(element, collection)
- assertIsInstance(object, type)
- assertNotIsInstance(object, type)
- assertRaises(exception, callable)
- assertRaisesRegex(exception, regex, callable)
- assertWarns(warning, callable)
- assertWarnsRegex(warning, regex, callable)
Видове тестове
- Unit tests - проверяват дали дадено парче код/клас работи правилно в изолация
- Integration tests - проверяват дали няколко модула си общуват правилно
- Functional tests - проверяват дали крайната функционалност е както се очаква
За какво ни помагат тестовете
- Откриват грешки по-рано
- Позволяват ни уверено да правим промени в системата
- Дават сигурност на клиенти, шефове и програмисти
- Представляват пример как се работи с кода
- Помага разделянето на интерфейс от имплементация
- Служат като документация и спецификация
За какво не служат тестовете
- Не доказват, че приложението работи
- Не са Quality Assurance
- Не са benchmark
Още речник
- black-box тестове
- glass-box тестове
- fixture (setUp и tearDown)
Документация
class Foo:
"""
Sample Foo class
"""
def foo(self):
"""
Sample foo method
Returns: 2
"""
return 2
Документацията като тестове
def add(a, b):
"""
Adds the two arguments.
>>> add(1, 3)
4
>>> add(1, '')
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'int' and 'str'
"""
return a + b
if __name__ == '__main__':
import doctest
doctest.testmod()
Дизайн
Въпрос: какво е "дизайн" на едно приложение?
Test-Driven Development
Test-Driven Development is not about testing.
Test-Driven Development (2)
- Добави тест
- Пусни всички тестове и виж, че новият се чупи
- Напиши код
- Пусни тестовете и виж че минават успешно
- Подобри кода (refactor)
- Повтаряй
Test-Driven Development (3)
- Подход за писане на код
- Дизайна е базиран върху обратна връзка, не гадаене
- Спестява излишен код -- пишете само каквото ви трябва
- Спестява излишна функционалност
- Продуктивност!
Behaviour-Driven Development
- Теst-Driven Development by Example
- The RSpec Book
- xUnit Test Patterns
Шепа съвети
- Пишете тестове за всичко, което може да се счупи.
- Не тествайте елементарен код.
- Не използвайте произволни тестови данни.
- Успеха на тестовете не трябва да зависи от реда им.
- Тествайте гранични случаи!
- Не правете тестовете зависими един от друг.