Как стать автором
Обновить

Комментарии 29

Извини за оффтоп, а если я не нажал на «Я соглашаюсь… бла бла бла», а нажал на ссылочку «Комментарии», это считается что я согласился, или нет?
Да. Я просто хочу, что бы не было copy-past этой статьи без указания автора (меня) и к тому же, что бы кто-либо делал на ней деньги. Думаю, это пожелания каждого автора на хабре.
Ну так надо было посто в конце статьи поставить соответствующий указатель, в виде картинок, и все) Вот например гугло поиск выдаст результат сразу на твой топик, и не будет видно лицензии.
ОК. Как-то не вспомнил о лого.
НЛО прилетело и опубликовало эту надпись здесь
>> Тест, который никогда не упал — бесполезный тест
Ничего подобного. Если я пишу тест, то я уверен, что потом, после рефакторинга эта часть кода не сломается. И могу не думать о ней.
Вы уверены в том, что если эта часть кода сломается, то тест завалиться. То есть уверенности придает его потенциальная способность завалиться.
НЛО прилетело и опубликовало эту надпись здесь
Суть-то в том, что вы уверены, что часть кода не сломается, именно из-за теста. Т.к. он «упадет», если изменения в программе будут неправильные. Ценность теста именно в том, что он «падает» и сигнализирует о логической ошибке. А тест, который заведомо не будет падать, и писать незачем.

Вы, скорее всего, просто неправильно поняли предложение (или даже одно слово — «упал»), т.к. пишете-то все верно)
согласно законам Мерфи… если этот код никогда не должен падать, то в него обязательно закрадется ошибка.

понятно, что писать ok( 1 == 1 ) не нужно.
Но вот проверить, что функция вернула неотрицательное количество пользователей — стоит. Пусть этого и не может быть.
Но для того чтобы убедиться что этот тест написан верно нужно обязательно вернуть отрицательное количество пользователей и убедиться что он «упал».
Хорошая выжимка из книги Кента Бека «Экстремальное программирование».
Хотя основная идея это вселить смелость в разработчиков, что можно безболезненно менять любую часть проекта, проводить любой требуемый рефакторинг, а не откладывать все это и пользоваться устаревшими реализациями.
Хорошая статья, но я не увидел в ней такой не популярный аспект как например то что тесты должны быть детерминированными, я что то упустил или уже это не актуально?
Это точно, но иногда этого сложно добиться, например, когда целью программы является моделирование и как следствее в ней активно используются случайные значения. В той задаче, с которой я сталкивался, мне повезло и после анализа я смог свести всю случайность в программе к случайным начальным данным, а сам алгоритм оказался детерминированным и мне удалось для него написать нормальные тесты.
НЛО прилетело и опубликовало эту надпись здесь
Думаю, что когда-нибудь будет — мне эта тема интересна. А само утверждение это просто чистая интуиция, дело в том, что тестирование активно используется программистами, пишущими на динамичиских языках, то есть тестирование для них это замена типизации. Далее я ступаю на почву: согласно изоморфизму, типы есть теоремы, а программы доказатества; в нашем случае, тогда, тесты есть теоремы.
Завалиться, становиться — уберите мягкие знаки…

По теме: «если код будет написан после тестов, то это гарантирует, что тест завалится» — что-то я не поняла этого утверждения, можно поподробнее?
если написать тест, а код который он тестирует не написать, то тест просто обязан завалиться
> Писать книги я не умею, да и опыта мало, но поделиться некоторыми аспектами использования unit тестов я могу

Точно не интересно попробовать формат пошире? Хотя книги по TDD есть, я думаю, тут ещё об очень многих аспектах можно порассуждать.

По крайней мере, я сам в повседневной практике усиленно пытаюсь внедрить TDD, но что-то всё время мешает. Сам я объясняю себе это сложностью и спецификой предметной области, но любой спец, скорее всего, легко раскритикует и объяснит как надо. Так что бы от хорошей книжки не отказался ;)
Вероятно, вам мешает выбранный вами тест-фреймворк:)
НЛО прилетело и опубликовало эту надпись здесь
> но что-то всё время мешает

Если не сложно, не могли бы вы описать несколько примеров, что мешает?
Довольно трудно сформулировать кратко :) Но попробую.
Для начала: мы пишем что-то вроде «конструктора» для создания систем искусственного интеллекта. По существующим спецификациям интерфейса пользователь должен написать свои собственные модули, потом система интегрируется в одно целое. Кроме того, мы поддерживаем инструментарий для отладки и анализа систем, а также выступаем в роли «пользователей», то есть сами пишем интеллектуальные агенты используя свой «конструктор».

Проблемы:
1) cложность и нечёткость предметной области. Если бы я писал библиотеку функций с понятным чётким поведением (тригонометрия, линейная алгебра) вопросов бы не было.
2) (редко, но бывает) ветвистость алгоритмов. Иногда у нас возникает куча кейсов типа «если-то», причём по отдельности каждый кейс выглядит довольно простым. Сочинять для такого тесты, честно говоря, ломает, потому что каждый случай тривиален, а чтобы покрыть большинство вариантов, уходит много кода. Покрыть же небольшую часть смысла мало, т.к. тогда тест становится не очень полезным.
3) в целом не очень большая польза от атомарных тестов в ИИ :) в большинстве случаев откомпилировать программу и заставить её работать по спецификации не очень трудно. Но оказывается, что работает интеллект плохо :) Приходится изменять параметры, влияющие на поведение, добавлять новые анализируемые факторы и т.п. То есть основной «дебаг» заключается в дополнительном анализе предметной области, а не в сверке со спецификацией.
4) (самый важный технический трабл). Наш «конструктор» можно представить себе ещё так. Есть инфраструктура с «дырками», для которой надо написать модули, затыкающие эти «дырки». Друг без друга ничего не работает. Чтобы запустить систему, нужны все модули (хотя бы в виде заглушек). Соответственно, чтобы тестировать инфраструктуру, нужны все модули (пусть хотя бы mock objects). А чтобы тестировать модули, нужна инфраструктура (впрочем, это уже не очень страшно). При этом всё развивается, иногда приходится менять слегка инфраструктуру под конкретный проект или добавлять в модули то, чего там быть не должно. В результате получается, что полноценный тестовый комплект может быть очень велик, включая в себя mock object едва ли не для любой сущности системы. Я склоняюсь к тому, чтобы рано или поздно стиснуть зубы и сделать эту работу. Но пока никак :)
5) (ерунда, но всё-таки) GUI-инструменты так тестировать вообще не получается.

В результате мы сейчас пользуемся в основном «feature-тестами». Собираем всю систему — от начала до конца, вначале состоящую из заглушек. Потом даём ей простые задания (это ведь интеллект, он должен выполнять какую-то работу в каких-то условиях). Если очередной модуль, который мы пишем, справляется со своей работой, то задание выполняется. Если не выполняется, ищем ошибку в модуле.
И так раскручиваем систему. Для готовой системы у нас есть непростые «задачки», для которых известен вход и выход, а также понятно, какой модуль реально должен эту задачу решить. Стало быть, если не решает, мы можем предположить, где именно баг…

В общем, сложно это всё, но интересно :)
Скажите, пожалуйста, где вы работаете — я с радостью пойду к вам в команду. Почему-то везде, где мне приходилось побывать, слова «тесты» «юнит-тестинг» и т.п. вызывали у менеджмента или непонимание, или полное отторжение, аля «мы не успеем сделать программу».
У Сергея Зефирова была мысль, что динамическая типизация это вывод типов для бедных
Спасибо, я теперь знаю как зовут автора одно из моих любимых блогов)
> Тест, который никогда не упал — бесполезный тест

Вы пытаетесь доказать это утверждение или это аксиома?

> Если ввести условие, что тесты не являются бесполезными,
> то тогда следует, что хороший тест должен хоть раз завалить программу.

У вас две этих фразы ссылаются друг на друга. Вы утверждаете что
упавший тест не бесполезен предполагая что
тест не бесполезен и получаете то что тест должен падать.

«ты не прав, потом что предположем, что ты не прав, следовательно ты не прав» :-)

На самом деле мне кажется это можно доказать ссылаясь на старую истину (и принимая ее как аксиому), что невозможно написать программу без ошибок и следовательно, если тест не падает, значит он просто не обнаруживает ошибку в программе, которую тестирует.
Да, не хорошо получилось.
Смысл в том, что если вы решили использовать тесты, то вы уже считаете, что тесты это хорошо и уже считаете их применение оправданным. Взявь эту уверенность за аксиому, получаем следствие про то, что тесты должны падать. В итоге можно читать следующем образом: если я верю в то, что тестирование приносит пользу, то я обязан верить и то, что тест, который никогда не завалиться — бесполезный тест. Надеюсь теперь стало яснее.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории