Слайды с конференции PyCon Siberia 2016.
Каждый программист рано или поздно начинает писать тесты на свой код. В какой-то момент он начинает задумываться о том, насколько его тесты хороши. В своем докладе я расскажу о том, какие инструменты для проверки качества тестов существуют, как они работают и почему они обманывают нас.
2. Обо мне
✤ Спикер PyCon Russia 2016,
PiterPy#2 и PiterPy#3
✤ Люблю OpenSource
✤ Не умею frontend
3. ✤ 15 лет практического опыта на рынке ИБ
✤ Более 650 сотрудников в 9 странах
✤ Каждый год находим более 200 уязвимостей
нулевого дня
✤ Проводим более 200 аудитов безопасности в
крупнейших компаниях мира ежегодно
4.
5. MaxPatrol
✤ Тестирование на проникновение (Pentest)
✤ Системные проверки (Audit)
✤ Соответствие стандартам (Compliance)
✤ Одна из крупнейших баз знаний в мире
Система контроля защищенности и соответствия
стандартам.
6. ✤ Тестирование на проникновение (Pentest)
✤ Системные проверки (Audit)
✤ Соответствие стандартам (Compliance)
✤ Одна из крупнейших баз знаний в мире
Система контроля защищенности и соответствия
стандартам.
✤ Системные проверки (Audit)
MaxPatrol
45. Выполненные строки
sys.settrace(tracefunc)
Set the system’s trace function, which allows you to implement a
Python source code debugger in Python.
Trace functions should have three arguments: frame, event, and
arg. frame is the current stack frame. event is a string: 'call',
'line', 'return', 'exception', 'c_call', 'c_return', or
'c_exception'. arg depends on the event type.
46. PyTracer «call» event
✤ Сохраняем данные предыдущего контекста
✤ Начинаем собирать данные нового контекста
✤ Учитываем особенности генераторов
50. Зачем такие сложности?
1 for i in some_list:
2 if i == 'Hello':
3 print(i + ' World!')
4 elif i == 'Skip':
5 continue
6 else:
7 break
8 else:
9 print(r'¯_(ツ)_/¯')
56. Мутационное тестирование
✤ Берем тестируемый код
✤ Мутируем
✤ Тестируем мутантов нашими тестами
✤ Если тест не упал -> это плохой тест✤ Тест не упал -> плохой тест
59. Идея
def mul(a, b):
return a * b
def test_mul():
assert mul(2, 2) == 4
def mul(a, b):
return a + b
def mul(a, b):
return a ** b
60. Идея
def mul(a, b):
return a * b
def test_mul():
assert mul(2, 2) == 4
assert mul(2, 3) == 6
def mul(a, b):
return a + b
def mul(a, b):
return a ** b
91. mutpy
def _matching_loader_thinks_module_is_package(loader, mod_name):
#...
raise AttributeError(
('%s.is_package() method is missing but is required by Flask of '
'PEP 302 import hooks. If you do not use import hooks and '
'you encounter this error please file a bug against Flask.') %
loader.__class__.__name__)
class InjectImporter:
def __init__(self, module):
# ...
def find_module(self, fullname, path=None):
# ...
def load_module(self, fullname):
# ...
def install(self):
# ...
def uninstall(cls):
# ...
97. pip install pytest-django
Name Stmts Miss Cover Missing
---------------------------------------------------
billing/views.py 8 0 100.00%
py.test --cov-config=coverage.ini
--cov=billing.views
billing/tests.py
Name Stmts Miss Branch BrPart Cover Missing
-----------------------------------------------------------------
billing/views.py 8 0 2 0 100.00%
py.test --cov-config=coverage_branch.ini
--cov=billing.views
billing/tests.py
98. mutpy
[*] Start mutation process:
- targets: billing.views
- tests: billing.tests
[*] Tests failed:
- error in setUpClass (billing.tests.TestCase1) -
django.core.exceptions.ImproperlyConfigured: Requested setting DATABASES,
but settings are not configured. You must either define the environment
variable DJANGO_SETTINGS_MODULE or call settings.configure() before
accessing settings.
mut.py --target billing.views --unit-test billing.tests