Информация об изменениях

Сообщение Re[7]: дебагинг vs unit-тесты vs ассерты от 30.04.2016 18:26

Изменено 01.05.2016 10:12 landerhigh

Здравствуйте, Кодт, Вы писали:

К>А интеграционные тесты — или ты устроишь комбинаторный взрыв, покрывая все мыслимые сочетания,


Вот для того, чтобы не устраивать комбинаторный взрыв в интеграционных тестах, и нужны юнит-тесты, чтобы все возможные варианты работы юнита тестировать в изоляции. Интеграционные тесты должны тестировать интеграцию, не более.

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


Проблемные места имеют такое противное свойство, что могут возникать и после того, как их вроде бы как все "выяснили" во время отладки.

L>>>>Не говоря уже о том, что от написания какого-то кода, зарытого глубоко под капот системы, засунутой под капот подсистемы, засунутой в подмодуль модуля основной программы, до возможности его запустить в составе этой самой программы, может пройти полгода-год.


К>Интеграционный тест должен будет потратить столько же времени для проверки, наигрывается или нет тот самый баг. Если какой-то больной модуль ровно через год запускается.


Не должен. Это ответственность юнит-теста.

К>Например, реальный баг: после нажатия на кнопку [_] окошко не сворачивается, а захватывает мышь и тупит. Что это за хрень?

К>Ты пишешь тест: mainwindow()->minimize(). Тест проходит.

Ничего не пишу. От слова совсем. Тесты уже есть, и тесты позволяют исключить 100500 юзкейсов из подозрения. В данном случае, тесты гарантируют, что если сообщение доходит до обработчика бизнес-логики, то оно обрабатывается в 100% случаев. Значит, проблема либо в том, что сообщение как-то неправильно обрабатывается в нашем обработчике, либо имеем место недокументированного поведения операционной системы. То есть вариантов вообще практически нет. Изолируем, включаем лог в обработчике и смотрим, что приходит на вход. То есть вообще ничего делать не надо. 15 минут — и WFT найден.

К>А может быть, проще было не выдумывать тесты, а запустить дебаггер и Spy++, и смотреть, как диспетчится мышь?


Ничего выдумывать не нужно, все уже есть. Включаю лог и смотрю. Если уж совсем припрет, можно и отдалчик привлечь, как крайнюю меру.

К>Не обманывай себя. Тесты пишет человек.


Хмм, а в отладчик кто смотрит, супермен, что ли?

K>Вот насколько у тебя хватило фантазии покрыть предметную область, настолько ты и написал тесты.


Особой фантазии для хорошего покрытия не требуется. Требуется желание разбивать модули так, чтобы свести домены вариантов использования к минимуму и покрывать их в принципе стандартным способом.

К>Сделал, к примеру, транспонирование матрицы на месте, но она у тебя, скажем, стреляет по памяти при НОД(x,y)=17, а стрельба сходит с рук при x<100.

К>Да, ты написал тесты о том, что матрица транспонируется. Разумеется, только при маленьких размерах и выборочно (ну не перебирать же все x от 1 до 200 и y от 1 до 200).
К>А что ты сделал для проверки стрельбы?

Во-первых, don't write shit code. Моей фантазии не хватает на то, чтобы представить, как можно в коде транспонирования матрицы случайно такой косяк допустить.
Во-вторых, проверка стрельбы по памяти не входит в ответственность юнит-тестов. Я в принципе не уверен, что ее можно в общем случае обнаружить в момент собственно выстрела.
В-третьих, используя тот факт, что дважды транспонированная матрица равна самой себе, в случае подобных подозрений можно написать и автотест, который переберет все варианты и сделает это за O(x*y) время, что в 21 веке означает примерно "мгновенно".
Re[7]: дебагинг vs unit-тесты vs ассерты
Здравствуйте, Кодт, Вы писали:

К>А интеграционные тесты — или ты устроишь комбинаторный взрыв, покрывая все мыслимые сочетания,


Вот для того, чтобы не устраивать комбинаторный взрыв в интеграционных тестах, и нужны юнит-тесты, чтобы все возможные варианты работы юнита тестировать в изоляции. Интеграционные тесты должны тестировать интеграцию, не более.

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


Проблемные места имеют такое противное свойство, что могут возникать и после того, как их вроде бы как все "выяснили" во время отладки.

L>>>>Не говоря уже о том, что от написания какого-то кода, зарытого глубоко под капот системы, засунутой под капот подсистемы, засунутой в подмодуль модуля основной программы, до возможности его запустить в составе этой самой программы, может пройти полгода-год.


К>Интеграционный тест должен будет потратить столько же времени для проверки, наигрывается или нет тот самый баг. Если какой-то больной модуль ровно через год запускается.


Не должен. Это ответственность юнит-теста.

К>Например, реальный баг: после нажатия на кнопку [_] окошко не сворачивается, а захватывает мышь и тупит. Что это за хрень?

К>Ты пишешь тест: mainwindow()->minimize(). Тест проходит.

Ничего не пишу. От слова совсем. Тесты уже есть, и тесты позволяют исключить 100500 юзкейсов из подозрения. В данном случае, тесты гарантируют, что если сообщение доходит до обработчика бизнес-логики, то оно обрабатывается в 100% случаев. Значит, проблема либо в том, что сообщение как-то неправильно обрабатывается в нашем обработчике, либо имеем пример недокументированного поведения операционной системы. То есть вариантов вообще практически нет. Изолируем, включаем лог в обработчике и смотрим, что приходит на вход. То есть вообще ничего делать не надо. 15 минут — и WFT найден.

К>А может быть, проще было не выдумывать тесты, а запустить дебаггер и Spy++, и смотреть, как диспетчится мышь?


Ничего выдумывать не нужно, все уже есть. Включаю лог и смотрю. Если уж совсем припрет, можно и отдалчик привлечь, как крайнюю меру.

К>Не обманывай себя. Тесты пишет человек.


Хмм, а в отладчик кто смотрит, супермен, что ли?

K>Вот насколько у тебя хватило фантазии покрыть предметную область, настолько ты и написал тесты.


Особой фантазии для хорошего покрытия не требуется. Требуется желание разбивать модули так, чтобы свести домены вариантов использования к минимуму и покрывать их в принципе стандартным способом.

К>Сделал, к примеру, транспонирование матрицы на месте, но она у тебя, скажем, стреляет по памяти при НОД(x,y)=17, а стрельба сходит с рук при x<100.

К>Да, ты написал тесты о том, что матрица транспонируется. Разумеется, только при маленьких размерах и выборочно (ну не перебирать же все x от 1 до 200 и y от 1 до 200).
К>А что ты сделал для проверки стрельбы?

Во-первых, don't write shit code. Моей фантазии не хватает на то, чтобы представить, как можно в коде транспонирования матрицы случайно такой косяк допустить.
Во-вторых, проверка стрельбы по памяти не входит в ответственность юнит-тестов. Я в принципе не уверен, что ее можно в общем случае обнаружить в момент собственно выстрела.
В-третьих, используя тот факт, что дважды транспонированная матрица равна самой себе, в случае подобных подозрений можно написать и автотест, который переберет все варианты и сделает это за O(x*y) время, что в 21 веке означает примерно "мгновенно".