Резюме: Нет.
i++
могло потенциально быть медленнее, чем ++i
, так как старое значение i
, возможно, должно было бы быть сохранено для более позднего использования, но на практике все современные компиляторы оптимизируют это далеко.
Мы можем продемонстрировать это путем рассмотрения кода для этой функции, и с ++i
и i++
.
$ cat i++.c
extern void g(int i);
void f()
{
int i;
for (i = 0; i < 100; i++)
g(i);
}
файлы являются тем же, за исключением ++i
и i++
:
$ diff i++.c ++i.c
6c6
< for (i = 0; i < 100; i++)
---
> for (i = 0; i < 100; ++i)
Мы скомпилируем их, и также получим сгенерированный ассемблер:
$ gcc -c i++.c ++i.c
$ gcc -S i++.c ++i.c
И мы видим, что и сгенерированные объектные и ассемблерные файлы являются тем же.
$ md5 i++.s ++i.s
MD5 (i++.s) = 90f620dda862cd0205cd5db1f2c8c06e
MD5 (++i.s) = 90f620dda862cd0205cd5db1f2c8c06e
$ md5 *.o
MD5 (++i.o) = dd3ef1408d3a9e4287facccec53f7d22
MD5 (i++.o) = dd3ef1408d3a9e4287facccec53f7d22
По моему опыту, чем ниже уровень вашего кода (если не считать его тривиальным), тем более полезны модульные тесты по сравнению с усилиями, необходимыми для их написания. По мере того, как вы поднимаетесь вверх по пищевой цепочке, тесты становятся все более сложными и дорогостоящими.
Модульные тесты имеют решающее значение, потому что они сообщают вам, когда вы что-то ломаете во время рефакторинга.
Тесты более высокого уровня имеют свою ценность, но тогда они больше не называются модульными тестами; они называются интеграционными тестами и приемочными тестами. Интеграционные тесты необходимы, потому что они показывают, насколько хорошо различные программные компоненты работают вместе.
Приемочные испытания - это то, что заказчик подписывает. Приемочные тесты обычно пишут другие люди (не программист), чтобы представить другую точку зрения; программисты, как правило, пишут тесты того, что работает, тестировщики пытаются сломать это, проверяя то, что не работает.
Мокинг полезен только для модульных тестов. Для интеграционных и приемочных испытаний макетирование бесполезно, поскольку оно не задействует фактические компоненты системы, такие как база данных и коммуникационная инфраструктура.
Приемочные тесты обычно пишут другие люди (не программист), чтобы представить другую точку зрения; программисты, как правило, пишут тесты того, что работает, тестировщики пытаются сломать это, проверяя то, что не работает.Мокинг полезен только для модульных тестов. Для интеграционных и приемочных испытаний макетирование бесполезно, поскольку оно не задействует фактические компоненты системы, такие как база данных и коммуникационная инфраструктура.
Приемочные тесты обычно пишут другие люди (не программист), чтобы представить другую точку зрения; программисты, как правило, пишут тесты того, что работает, тестировщики пытаются сломать это, проверяя то, что не работает.Мокинг полезен только для модульных тестов. Для интеграционных и приемочных испытаний макетирование бесполезно, поскольку оно не задействует фактические компоненты системы, такие как база данных и коммуникационная инфраструктура.
Если вы выполняете TDD, вам следует писать тесты не после реализации, а наоборот. Таким образом, вы также избежите проблемы соответствия теста написанному коду. Вероятно, вам действительно нужно протестировать определенные вызовы методов в этих модулях, но не их последовательность (если это не обязательно для проблемы предметной области - бизнес-процесса).
И иногда вполне возможно не писать тест для определенного метода.
Я думаю, это сильно зависит от окружающей среды. Если вы работаете в относительно небольшой команде и можете поддерживать целостность тестирования, то более сложные части вашего приложения должны иметь модульные тесты. По моему опыту, поддерживать целостность тестов в больших командах довольно сложно, так как тесты изначально в порядке, пока они не неизбежно ломаются ... в этот момент они либо а) «исправлены», что полностью сводит на нет их полезность, либо б ) незамедлительно закомментирован.
Похоже, что основной смысл имитационного тестирования состоит в том, чтобы менеджеры могли утверждать, что показатель покрытия кода равен Foo% .... так что все должно работать! Единственный исключительный случай, когда они могут оказаться полезными, - это когда вам нужно протестировать класс, который очень сложно воссоздать аутентично (например, тестирование класса действий в Struts).
Я большой сторонник написания сырых тестов. Реальный код с реальными объектами. Код внутри методов со временем будет меняться, но цель и, следовательно, общее поведение обычно не меняются.
Просто коснусь вашего выделенного жирным шрифтом утверждения:
«Я должен проверить поведение метод, а не то, что он вызывает это ошеломляет и контрпродуктивно для меня. Я могу видеть ошибки в пользовательском интерфейсе, и да, насмешливое поведение на этом уровне имеет тенденцию быть хрупким. Я гораздо больше озабочен тем, чтобы мой базовый домен и слои DAL работали правильно.
То, что является значением на верхнем уровне, является тестом интеграции. Есть веб-приложение? Вместо того, чтобы утверждать, что методы вашего контроллера возвращают ActionResult (малоценный тест), напишите интеграционный тест, который запрашивает все страницы в вашем приложении и проверяет, нет ли 404 или 403. Запускайте его один раз при каждом развертывании.
Окончательный ответ
Я всегда следую правилу 80/20 при модульном тестировании . Чтобы получить последние 20% покрытия на высоком уровне, о котором вы говорите, вам потребуется 80% ваших усилий. Для моих личных и большинства моих рабочих проектов, это не окупается.
Короче, я согласен. Я бы написал интеграционные тесты и проигнорировал бы модульные тесты для кода, который вы описываете.
In general, I consider testing this type of method/command to be ripe for the integration testing level. Specifically, I "unit test" for smaller, low level commands that (generally) don't have side effects. If I really want to unit test something that doesn't fit that model, the first thing I do is see if I can refactor/redesign to make it fit.
At the higher, integration (and/or system) testing level, I get into the testing of things that have side effects. I try to mock as little as possible (possibly only external resources) at this point. An example would be mocking the database layer to: