Тестируя ваши тесты |
12.10.2023 00:00 |
Автор: Баз Дейкстра (Bas Dijkstra). В этой статье я хочу обсудить практику тестирования ваших тестов и поговорить о том, зачем это нужно, и как это делается. Дабы меня правильно поняли – говоря о тестах, я говорю о точках верификации, выполняемой инструментально, то есть о том, что множество имеющих отношение к тестированию людей называют «проверками». Возможно, хорошей идеей будет также тестирование ваших идей, мыслей и относящихся к тестированию процессов, но об этом сегодня речь не пойдет. Итак, зачем нам тестировать наши тесты? Я считаю это очень хорошей идеей по ряду причин:
Иными словами, мы должны иметь возможность доверять нашим тестам. Однако тесты, как и любое другое ПО, могут нас обмануть. В случае с тестами это обычно происходит при ложноположительных или ложноотрицательных результатах. Ложноотрицательные очень раздражают – они кричат «Волки», когда в тестируемом ПО нет никаких проблем. Как правило, проблемы кроются во временных привязках, синхронизации, тестовых данных или тестовом окружении. Но ложноотрицательные результаты хотя бы сообщают о себе, объявляя о падениях. В отличие от них, ложноположительные – это то, что я обычно называю «бесшумными убийцами»: они сообщают об успехе и дают изменению просочиться незамеченным. Вот упрощенный пример кода из воркшопа по мутационному тестированию, который я десятки раз проводил на конференциях и у клиентов: public void withdraw(double amountToWithdraw) throws WithdrawException { if (amountToWithdraw > this.balance && this.type.equals(AccountType.SAVINGS)) { // process funds withdrawal here Тест, написанный нами для покрытия этой логики: @Test Account account = new Account(AccountType.SAVINGS); assertThrows(WithdrawException.class, () -> account.withdraw(50)); Видите проблему? Разработчик может ошибиться (они живые люди, поэтому с шансами рано или поздно они это сделают) и случайно упустить вторую часть условного утверждения. Код будет выглядеть так: public void withdraw(double amountToWithdraw) throws WithdrawException { if (amountToWithdraw > this.balance) { // process funds withdrawal here Однако наш тест продолжит срабатывать, а покрытие кода останется стопроцентным. Если такой код уйдет на прод, то овердрафт станет невозможным для любых счетов, что потенциально приведет к сбитым с толку пользователям, а также к потере дохода для банка, который не сможет взимать процент за использование заемных средств. Это всего лишь один пример ценности тестирования своих тестов. Вместо того, чтобы полагаться на срабатывающие тесты и некий процент покрытия (кода), тесты стоит более тщательно… ну, тестировать. Вот ряд техник, которыми можно пользоваться для тестирования своих тестов:
|