Здравствуйте, Кодт, Вы писали:
К>Кто говорил "заменять"? Это ты всячески хочешь заменить отладчик тестами, а не я тесты отладчиком.
Нет, я предлагаю вылезти из каменного века и перестать точить кремниевые топоры гранитными камнями.
К>Видишь ли, вся арифметика — это сплошные граничные условия.
К>И ты либо пишешь на идрисе или каких-то тому подобных языках, с нумералами Пеано и прочами ужасами.
К>Либо соглашаешься на то, чтоб какую-то совсем уж откровенную мелочёвку принять на веру. (А компилятор, в случае чего, тебя не простит и отомстит).
Что-то всегда нужно принять на веру, а то так можно договориться до того, что начинать нужно с юнит-тестов для операций процессора.
К>Почему факт зацикливания? Умный гусь или шланг в -O3 способен творить чудеса, и на нашем форуме уже приводили примеры — как он и бесконечный, и пустой цикл создавал, и через условия перепрыгивал. Потому что Undefined даёт широкие возможности. Например, отладочный код будет работать правильно (тесты-то компилятся с -O0 либо -Ox -DDEBUG), а релизный хаотично, и даже диск форматнуть может при известной ловкости рук.
Именно поэтому у нас проект сразу собирается в релизе и тесты гоняются тоже в релизе. Мы можем себе это позволить, поскольку при разработке отладчик нам использовать незачем. И это нас уже спасло от кучи именно таких приколов.
| cut |
| L>>Но ладно, в принципе, пример годный. Допустим, что исходный код имеет некий пока непонятный мне смысл. Сделаем неявное явным
L>>L>>template <class F>
L>>void go_around_zero_v2(int n, F func) {
L>> if (math::abs(n) > MAX_UINT/20 -1)
L>> {
L>> throw std::runtime_error("Loop will go bananas!");
L>> }
L>> for(int i = -n*10; i <= n*10; ++i) {
L>> func();
L>> }
L>>}
L>>void go_around_zero(int n)
L>>{
L>> go_around_zero_v2(n, do_smth);
L>>}
L>>
|
| |
L>>Примерно все.
К>Моя мина-ловушка всё-таки сработала! abs(INT_MIN) даёт неопределённое поведение, если INT_MIN < -INT_MAX.
Не сработала. Эта мини-ловушка не пройдет тест для граничных условий. Я просто в очередной раз наступаю своей же песне на хвост — тест с INT_MIN я напишу вторым, после INT_MAX. Мне это очевидно, тем, кто тесты писать не привык, нет. Я же говорю — тесты пишутся для граничных условиях на автомате за считанные секунды. Иногда приходится задуматься, как в случае с INT_MIN, чтобы понять, сколько же итераций в данном случае ожидается.
(А потом аффтар кода вспомнит, что писать код под гриппом с температурой — это еще хуже, чем под веществами (наверное) и больше этого делать не будет)
К>После чего вылезает оптимизатор (который тоже посчитал границы цикла с неопределённым поведением) и делает там что-то очень странное. Но в тесты это не попадёт, потому что тестовое окружение задавило оптимизацию.
Не делает — тест гоняются в релизе. И волосы остаются мягкими и шелковистыми.
К>Через три месяца Виллабаджо захватила свою долю рынка бета-версией продукта, дерзкой и как пуля резкой, а Вилларибо продолжает обкладывать арифметику тестами и/или выпускать гигантского ленивца (каждая проверка имеет свою цену в байтах и наносекундах).
Нет, не так. Через два месяца Виллариба выпустила стабильный первый релиз продукта, захвативший весь рынок. Через еще два — второй стабильный.
А виллабаджо никак из нестабильной беты вылезти не может.
Слушай, не надо только меряться. Ну не увеличивает использование тестов время разработки. Уменьшает. Часто — очень значительно уменьшает. А уж разница после передачи проекта в QA... но тут нужно один раз увидеть, чтобы поверить.