Unit Test. Кто использует?
Ну дык я ж копировал цитату Ошерова из сети:
The main thing to remember about mocks versus stubs is that mocks are just like stubs, but you assert against the mock object, whereas you do not assert against a stub.
И в примере было что в объекте собираются данные, а потом ассертом проверяются.
а стаб - чтобы вернуть нужное значение
Не-а, моком тоже могу вернуть нужное значение. Разный подход. В стабе мы имплепентируем метод, а моку говорим "у тебя вызовут divide(4,2) а ты вернешь 10".
По-моему, это стаб создается для того, чтобы вернуть значение. Причем "правильное", которое нужно для того, чтобы прошел наш тест. И мы проверяем, получили ли мы В ТЕСТИРУЕМОМ ОБЪЕКТЕ ожидаемый результат. А мок создается, чтобы проверить, правильно ли тестируемый объект общается с внешним миром. И проверяем мы это не в тестируемом объекте, а В МОКЕ, правильно ли наш объект с ним общался (вызывал, посылал данные, сообщения, ...)
Приватные методы это и статическая инициализация это да, больно. Если нельзя менять код, то может помочь PowerMock
Если надо "замОчить" приватный, статический метод или даже конструктор. Баловство с байткодом и класслоадерами.
А вот вызовы Ejb можно подменить. С помощью reflections можно переписать значение даже финального поля. Подменишь Factory на свой мок - и вперед.
Я уже разобрался с JMockit.
Комбинация мокапов с "ожиданиями" довольно мощная.
public class VOCreaterTest {
@Mocked
private BenutzerVO benutzer;
@Test
public void createVO_Vorgang() throws Exception {
new MockUp<ObjectCacheSingleton>() {
@Mock
public synchronized CacheEntry getCachedObject(ObjectKey key) {
if (key.getKey().equals(CacheConstants.KEY_LIST_VORGANGSTATUS)) {
CacheEntryImpl entry = new CacheEntryImpl();
FKValue fk = new FKValue();
fk.setKey(CacheConstants.VORGANGSTATUS_OFFEN);
entry.setObject(fk);
return entry;
}
return new CacheEntryImpl();
}
@Mock
public void initializeCachedObjects() {
}
};
new MockUp<ObjectmanagementUtil>() {
@Mock
public VorgangVO loadVorgangDaten(VorgangVO vorgang, String schadenId, FKValueWithSchadenschluessel beteiligtenrollen, FKValueWithSchadenschluessel fahrzeugrollen, String messageAlle) {
return null;
}
};
new MockUp<Logger>() {
@Mock
public void debug(Object message) {
}
};
VOCreater creater = new VOCreater();
VorgangVO vo = (VorgangVO) creater.createVO(SamVO.VO_TYPE_VORGANG, null, benutzer);
assertTrue(vo.isOffen());
}
@Test
public void createVO_Schaden() throws Exception {
new MockUp<ObjectCacheSingleton>() {
@Mock
public synchronized CacheEntry getCachedObject(ObjectKey key) {
return new CacheEntryImpl();
}
@Mock
public void initializeCachedObjects() {
}
};
VOCreater creater = new VOCreater();
SamVO vo = creater.createVO(SamVO.VO_TYPE_SCHADEN, null, benutzer);
assertTrue(vo instanceof SchadenVO);
SchadenVO schadenVO = (SchadenVO) vo;
assertNotNull(schadenVO.getSachbearbeiter());
}
}
Правда, у автора похоже clean code головного мозга, а развитие фреймворка идет в сторону чистого тестирования.
Какой молодец. Кто б еще PowerMock зарезал бы...
Как задолбали программизды, которые вместо переделки кода лепят тесты, для которых надо перегружать классы, модифицировать байткод...
Скоро потребуют им свою JVM написать. Для тестов, ага. Тесты ведь для того и нужны чтобы найти плохой код, который надо переписать.
Если ты его даже протестировать не можешь, как ты его расширять / модифицировать будешь?
Наши уже доигрались. В 8-й яве улучшили JIT, он теперь распознает статические методы, возвращающие значение static final-а
и при определенном количестве вызовов тупо подменяют в коде вызов на значение поля. Измениться-то оно не может, final же.
И теперь все тесты, где наши дэбилы тупо подменяли значение final-ов не работают. Подменяй - не подменяй, а если заинлайнено не поможет.
Я 5 лет им мозги поласкал, что нельзя так делать, переделайте код, могут проблемы быть. А теперь бегают вокруг и воют - сделай что-нибудь, а то у нас не работает ничо....
А отключать инлайниг полностью не вариант - тесты в 4-5 раз дольше работают.
Слава богу я хоть использование PowerMock-а у нас сделал настолько неудобным, насколько можно. А то бы еще и из-за приватных методов мозги клевали бы постоянно.
Допиливать подразумевает править код, верно? Вот в процессе написания тестов и правь. Видишь доступ к чужому синглтону, спрячь за своим get-ом.
Вместо
EjbFactory.getInstance().getBean()
будет у тебя
protected EjbFactory getEjbFactory(){ return EjbFactory.getInstance();} и getEjbFactory().getBean() вызов.
Всё. Хочешь - в подклассе переопределяй, хочешь в моке эмулируй.
Допиливать подразумевает не трогать лишнего :)
My problem is that the real world is not just about good code. One is often facing a ugly old codebase where you need to fix that one special bug and then leave the rest behind.
You neither have the time nor the intention to fix all those design and structural issues that where made in the past, but you want to get a basic feeling that your bugfix might work in production too.
So you mock as much as possible, isolate the problem, fix it and leave the test there so no one else will break it again.
Угу. Только на написание такого теста уходит в два раза больше времени чем на правку кода, а потом ошибки лезут в тестах чаще раз этак в 100 чем а тестируемом коде.
У нас такое есть. Чтобы тестировать создание страховых случаев полсистемы моками меняем. А потом каждую неделю правим моки. Потому что то в одном модуле выбросили приватное поле, то в другом поменяли количество параметров у приватного же метода. TCO для таких тестов лучше не считать.
Я только в одном классе (фейк доступа к одному типу классов) только за последний год несколько десятков!!! правок делал. И каждая стоит время. Часа 2-3 пока поймешь что изменилось и что теперь можно сделать. Половину системы перевели на DI и расзод времени на правку тестов упал до незаметного, а у второй половины...
У команды "нет времени". А тесты править каждую неделю и выть часами на совещаниях что мы им должны вынуть и положить кнопку "поправь тест за меня" - есть.
NP.
MS Tests.
Интеграционные тесты.Для выполнения тестов необходимо иметь разные наборы данных в базе (Оракле).
Имею код, создающий в тестовой базе нужные таблицы.
Имею несложный код заполняющий базу нужными данными.
Работает так: при инициировании теста создаются задействованные таблицы, туда
вгоняются данные, отрабатывает тест, все дропается.
Имею проблему: подготовка данных для тестов занимает избыточно много времени.
Имеется в виду не процессорное время для вбивания данных и выполнения теста,
а время на подготовку скриптов вбивания данных.
При этом данные из базы извлекаются уже в виде полуготового скриптового кода.
Т.е. Я получаю строку вида table,AddRow(1, 2, 3, "", DateTime.Parse("24/12/206"));
дальше - копипасте и фиксинг неправильных параметров.
Есть какая методика по упрощению процесса?
ОК, ставлю вопром ребром: где найти в Германии ацуби, который бы написал бы тесты (не обязательно юнит-) с использованием всех паттернов, описанных в книжках месароша и искусстве автономного тестирования.
Ну и этот ацуби мог бы хотя бы после курсов Баранцева написать пару автотестов для крупного сайта. С использованием PageObject паттерна, да
Ключевое слово здесь - ацуби. Т.е.он должен иметь доход уровня Hatz-IV-щика и жить у родителей.