Re[20]: Про путаницу с репозиториями и DAO
От: another_coder Россия  
Дата: 29.06.16 11:11
Оценка:
Здравствуйте, gandjustas.

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

Вы писали:

G>Ты подменяешь понятия. Если можно написать юнит тест, это вовсе не означает, что им можно что-то проверить. Я несколько раз видел программы с тестовым покрытием близким к 100%, естественно юнит-тестами. В них были баги в огромном количестве.


G>Если у бабушки кое-что было, то она была бы не совсем бабушкой. Не делали интеграционные тесты по причине, описанной тобой выше. Покрыть интеграционными тестами значимую часть программы с разумными затратами невозможно. А юнит тестами можно. Вот только юнит-тесты не проверяют.


Я не подменяю понятия. Если гнаться только за покрытие кода тестами, то понятно, почему юнит-тесты ничего не проверяют. UT должно быть легко выкинуть, переписать, написать с нуля и запустить. Покрытие — это очень косвенный показатель. Юнит тесты необходимо проверять так же, как и остальной код, чтобы не было написания тестов ради самих тестов. По сути, это спасательные якоря скалолаза (самого разработчика), если образно. Их может быть не много, но там где надо.

G>>>Вот у тебя есть метод — делает выборку, обрабатывает, сохраняет. Это твой сценарий.

G>>>Для теста ты репозиторий подменяешь банальной реализацией на list<t>, когда метод просто отдает список. И проверяешь что данные в списке поменялись.
G>>>Ты написал код, который делает обработку, а SaveChangesAsync забыл. Тест проходит. При запуске не работает, тупо ничего не происходит.

_>>Я бы распилил на несколько методов, которые по-отдельности можно протестировать. Т.е. выборка проверялась бы интеграционным тестом, обработка — юнит тестом, сохранение — интеграционным. При этом в юнит тесте выборку и сохранение я бы замокал.

G>По-моему ничего бы не изменилось.

G>Код был примерно такой:

G>
G>void F(Repo repo)
G>{
G>    var xs = repo.GetXsByXXX();
G>    foreach(var x in xs)
G>    {
G>        x.y+=1;
G>    }
G>    // repo.SaveChanges(); // эту строку потеряли при рефакторинге
G>}

G>[Test]
G>void Test()
G>{
G>    var mock = new Mock();
G>    var xs = new [] { ... };
G>    mock.Xs = xs;
G>    F(mock);
G>    Assert.IsTrue(xs.All(...));
G>}
G>


G>Тест зеленый, код не работает.


G>Ты предлагаешь покрыть GetXsByXXX интеграционным тестом, что не имеет смысла, там примитивный запрос. Покрыть SaveChanges интеграционным тестом, что тоже не имеет смылса и написать юнит-тест для F, что не дает фактически проверки.


Тут чтобы правильно ответить надо еще вопросов позадовать. Если интересно, то расскажите, в чем главная цель этого метода F (от этого зависит как он должен быть написан и какие тесты для него писать)? А так же интересно, ваш реп должен хранить состояние и беферизировать данные, или просто явлется прослойкой между ORM (EF, например) и BO?

G>У меня еще интереснее сценарий есть:

G>В приложении календарь. При создании нового события надо проверить, что событие не пересекается с существующим. Событий много, тянуть все в память нельзя, проверять надо запросом к базе. И важное условие — тебе повезло, ты не можешь использовать Linq, обязательно текстовые запросы.
G>Напиши юнит-тест для проверки.

Для проверки чего? Хранимки, динамического стейтмента, условий проверки? Описание не достаточно, чтобы нормально ответить вопрос.

G>Я этой задачей троллю апологетов юнит-тестов.


Можем попробовать по разбираться. Кому-то точно в + итоги будут. Если без попыток убедить и навязать свое мнение
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.