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

Сообщение Re[22]: Про путаницу с репозиториями и DAO от 30.06.2016 4:04

Изменено 30.06.2016 6:01 another_coder

Здравствуйте, gandjustas.

И так, суммирую:
1) репозиторий просто прослойка (facade) к EF.
2) необходимо проверить генерацию запросов (стейтментов)

Оригинальный псевдокод такой:
bool F(Event evt)
{
    string query = buildQuery(evt);
    ResultSet rs = db.query(query);
    if(rs.Count>0) 
    {
        return false; 
    } 
    else 
    {
        db.addEvent(evt);
        return true;
    }
}


G>Зеленый UT должен показывать что код отработает корректно в продакшене, если база будет доступна.

Вот тут поправлю: UT покажет, что алгоритм генерации запросов работает так, как разработчик предполагает он должен, а интеграционный тест покажет как потом он работает на _тестовом_ окружении. Не стоит полагать, что тесты заткнут все возможные дыры, даже еще не встреченные.

Что я сделала бы...

1) необходимо иметь возможность мокать:
db.query(query)
db.addEvent(evt)
Не знаю что из себя представляет db. Это интерфейс? Как создается/инжектится?

2) buildQuery(evt) необходимо передать другой сущности, которая занимается его построение. Тогда:
— можно будет отдельно протестировать
— как следствие, можно будет замокать в тестах
Например, вынесем в другой class QueryBuilder : IQueryBuilder {}

На этому этапе код может, предположительно, выглядеть так, после изменений:
bool F(IDb db, IQueryBuilder qBuilder, Event evt)
{
    string query = qBuilder.buildQuery(evt);
    ResultSet rs = db.query(query);
    if(rs.Count>0) 
    {
        return false; 
    } 
    else 
    {
        db.addEvent(evt);
        return true;
    }
}


3) В этом случае на метод F можно написать такие тесты (проверяем ветви алгоритма):
— должен возвращать false, если rs.Count>0
— должен возвращать true, если rs.Count<=0
— должен вызвать addEvent с переданным evt, если rs.Count<=0

4) Отдельно можно протестировать генерацию запросов в методе buildQuery класса QueryBuilder. Не знаю деталей, но девелопер же написал алгоритм генерации, значит может подавая на вход разные evt проверить построение соответствующих для них строк. Получится несколько тестов.

5) Я полагаю, что в db.query только сам механизм вызова БД. Поэтому, в интеграционном тесте проверяем, что:
— переданный запрос в db.query вернул то, что требовалось запросом.
Этот тест покажет, что этот метод получает данные из базы и адекватно выполняет запросы, что и требуется.

В итоге получилось UT 3+ и IT 1 = 4 или более тестов.

Теперь представим, что вносили какие-то изменения. Может оказаться так, что все зеленное, но почему-то не работает на продакшене. Это проблема не тестов, а тестового окружения. Предположим, там лочится таблица, метод query падает. Тут понятно что делать. У вас все проверяется, кроме этого момента. Значит, специальным интеграционным тестом необходимо проверить этот момент, а метод buildQuery проапдейтить так, чтобы, например, он ставил (nolock).

Мысль понятна? Какие вопросы, несогласия?
Здравствуйте, gandjustas.

И так, суммирую:
1) репозиторий просто прослойка (facade) к EF.
2) необходимо проверить генерацию запросов (стейтментов)

Оригинальный псевдокод:
bool F(Event evt)
{
    string query = buildQuery(evt);
    ResultSet rs = db.query(query);
    if(rs.Count>0) 
    {
        return false; 
    } 
    else 
    {
        db.addEvent(evt);
        return true;
    }
}


G>Зеленый UT должен показывать что код отработает корректно в продакшене, если база будет доступна.

Вот тут поправлю: UT покажет, что алгоритм генерации запросов работает так, как разработчик предполагает он должен, а интеграционный тест покажет как потом он работает на _тестовом_ окружении. Не стоит полагать, что тесты заткнут все возможные дыры, даже еще не встреченные.

Что я сделал бы...

1) необходимо иметь возможность мокать:
db.query(query)
db.addEvent(evt)
Не знаю что из себя представляет db. Это интерфейс? Как создается/инжектится?

2) buildQuery(evt) необходимо передать другой сущности, которая занимается его построение. Тогда:
— можно будет отдельно протестировать
— как следствие, можно будет замокать в тестах
Например, вынесем в другой class QueryBuilder : IQueryBuilder {}

На этому этапе код может, предположительно, выглядеть так, после изменений:
bool F(IDb db, IQueryBuilder qBuilder, Event evt)
{
    string query = qBuilder.buildQuery(evt);
    ResultSet rs = db.query(query);
    if(rs.Count>0) 
    {
        return false; 
    } 
    else 
    {
        db.addEvent(evt);
        return true;
    }
}


3) В этом случае на метод F можно написать такие тесты (проверяем ветви алгоритма):
— должен возвращать false, если rs.Count>0
— должен возвращать true, если rs.Count<=0
— должен вызвать addEvent с переданным evt, если rs.Count<=0

4) Отдельно можно протестировать генерацию запросов в методе buildQuery класса QueryBuilder. Не знаю деталей, но девелопер же написал алгоритм генерации, значит может подавая на вход разные evt проверить построение соответствующих для них строк. Получится несколько тестов.

5) Я полагаю, что в db.query только сам механизм вызова БД. Поэтому, в интеграционном тесте проверяем, что:
— переданный запрос в db.query вернул то, что требовалось запросом.
Этот тест покажет, что этот метод получает данные из базы и адекватно выполняет запросы, что и требуется.

В итоге получилось UT 3+ и IT 1 = 4 или более тестов.

Теперь представим, что вносили какие-то изменения. Может оказаться так, что все зеленное, но почему-то не работает на продакшене. Это проблема не тестов, а тестового окружения. Предположим, там лочится таблица, метод query падает. Тут понятно что делать. У вас все проверяется, кроме этого момента. Значит, специальным интеграционным тестом необходимо проверить этот момент, а метод buildQuery проапдейтить так, чтобы, например, он ставил (nolock).

Мысль понятна? Какие вопросы, несогласия?