C unit-тестированием иногда бывает связан один иррациональный страх, природу которого я попытаюсь сейчас объяснить а так же показать, что бояться в общем-то нечего. Страх этот заключается в том, что правильность результатов unit-тестирования ставится под сомнение. А ну как скрипт ошибся и мы выдадим неработающий софт? По-хорошему подобные душевные метания возникать не должны. Потому что:

1. Если тест ошибётся и пропустит баг, то это будет эквивалентно ошибке тестировщика. Однако никто почему-то ручное тестирование не отменяет, люди как тестировали так и тестируют. Почему вероятность ошибки останавливает людей от применения unit-тестов? Непонятно.
2. Если тест ошибётся и пропустит баг, то это будет эквивалентно ошибке тестировщика. И в этом нет ничего страшного. Совершать ошибки - это часть человеческой природы1. И то что творения рук человеческих так же могут «ошибаться», нужно принять как данность. Надо просто следить чтобы количество таких ошибок не превышало допустимую норму отказов.
Например, есть у нас в войсках на вооружении один зенитно-ракетный комплекс. Очень хороший кстати. Так вот у этой очень сложной в техническом плане машины, от которой могут зависеть жизни сотен тысяч человек, вероятность поражения цели меньше единицы. Т.е. даже этому комплексу дается право на ошибку. Почему вероятность ошибки останавливает людей от применения unit-тестов? Непонятно.

    Теперь внимательно следите за руками. Unit-тесты никогда не дают гарантии корректности работы софта. Вывод о корректности работы тестируемого софта делает только человек. А unit-тесты таких выводов сделать не могут. Гарантия отсутствия ошибки и гарантия корректной работы это две принципиальные разницы, и это надо очень чётко понимать. Строго говоря, пройденный unit-тест говорит об отсутствии ошибки в проверяемом тесткейсе, но он ничего не говорит о корректности тестируемого usecase'а. Выводы о корректности тестируемой функциональности должен сделать тестировщик на основе результатов нескольких тестов. Мы запускаем unit-тест, задавая ему вопрос «Есть ли ошибка?». Если тест нам выдает «истину», то мы идем разбираться в чем же ошибка. Если тест нам выдает «ложь», то мы на основании одного этого ответа никаких выводов об истинности или ложности утверждения «Софт работает корректно» сделать не можем.

    Если говорить ещё более формально строго, то отрицательный результат каждого из unit-тестов не говорит нам абсолютно ничего. Это полностью соответствует поведению операции импликации в булевой логике, когда из истины может следовать истина, из истины может следовать ложь, из лжи может следовать ложь, но из лжи никогда не может следовать истина2.

    Каждая конкретная «ложь» нам ничего не дает. Однако, если в нескольких тестах была получена «ложь» на вопрос о наличии ошибки, то на основе этих данных уже можно делать выводы. Например, у нас есть функция f(x), возвращающая модуль своего единственного числового параметра. У нас будет три тесткейса:


1. когда x < 0, f(x) должно быть -x
2. когда x > 0, f(x) должно быть x
3. когда x = 0, f(x) должно быть 0

    Если первый тесткейс отработал корректно, т.е. вернул нам «false» на вопрос «Есть ли ошибка?», то это нам ничего не говорит, ведь может остальные тесты «отвалятся». Однако если все тесты вернут «ложь» в качестве ответа на тот же самый вопрос, то на основании этих данных уже можно сделать вывод о корректности работы функции. И в отчете о тестировании можно поставить «Протестировано. Ошибок нет.» Но эту запись поставит только человек а не машина. И по-хорошему нужно опасаться ошибок именно в работе человека, а не машины. Просто потому что его задача на порядок сложнее чем у unit-теста.

    Это как доказать/опровергать теорему «Софт работает корректно». Человек пытается её доказать, а unit-тесты опровергнуть. И именно поэтому задача человека на порядок сложнее, и поэтому вероятность (да и стоимость) человеческой ошибки выше вероятности и стоимости ошибки unit-теста (человека, писавшего unit-тест). Для того чтобы доказать теорему нужно обеспечить выполнение условия теоремы для всех входных данных из области определения, указанной явно или неявно в теореме, а чтобы опровергнуть теорему достаточно одного только частного случая, для которого утверждение будет ложным.

    Таким образом над тестами всегда будет Человек, интерпретирующий их свидетельства об отсутствии/наличии ошибок во время отработки тесткейсов. Человек всегда будет подстраховывать Машину и поэтому ошибок в работе Машины бояться не стоит.

PS Ссылки по теме:
Менеджер тестирования
Unit-тесты часть 3
Unit-тесты часть 2
Unit-тесты часть 1


1 перекладывать вину за эти ошибки ещё большая часть человеческой природы ) © Законы Мёрфи
2 лишний раз порадовался, что моё образование «прикладная математика» оказалось больше «математикой» нежели «прикладной» ))