Хорошо ли сортировать список в тесте тестового примера, чтобы проверить граничные данные?

Я тестирую результаты запроса. Таблица, в которой хранятся результаты, имеет такую ​​структуру:

Id  SomeValue  Date        Hour
-----------------------------------
1   foo1       2015-01-01  700
2   foo2       2015-01-01  800
3   foo3       2015-01-01  900
...
18  foo18      2015-01-01  2400
19  bar1       2015-01-02  100
20  bar2       2015-01-02  200
...
41  bar23      2015-01-02  2300
42  bar24      2015-01-02  2400
43  baz1       2015-01-03  100
44  baz2       2015-01-03  200
(and on...)

И запрос получает параметры для выполнения поиска на основе столбцов Date и Hour следующим образом:

SELECT *
FROM table
WHERE
    (date, hour) >= (:dateFrom, :hourFrom)
    AND (date, hour) <= (:dateTo, :hourTo)
-- there no ORDER BY clause in the query

Например, если я использую следующие значения:

  • dateFrom: '2015-01-01'
  • hourFrom: 700
  • dateTo: '2015-01-03'
  • hourTo: 600

Запрос возвращает все строки, где значение Date находится между 2015-01-01 и 2015-01-03, значения Hour больше или равны 700 только для Date = 2015-01-01, а значения Hour меньше или равно 600 для Date = 2015-01-03. В этом примере все строки с Date = 2015-01-02 будут извлечены из источника данных.

Я получаю результаты выполнения запроса в списке. Чтобы оценить результаты, я использую значения параметров, которые я использовал, чтобы проверить, соответствуют ли данные в списке. Я использую метод проверки, если дата элемента находится между dateFrom и dateTo, но мне интересно, как я могу проверить значения hourFrom и hourTo. У меня есть следующие идеи:

  • Начните проверять значение minumum Hour на элементах, где значение Date равно моему параметру dateFrom и проверьте, равно ли это значение hourFrom. Сделайте подобное для hourTo, но с максимальным значением тех строк, где значение Date равно значению параметра dateTo.
  • Сортируйте список в моем методе тестирования Date и Hour, затем проверьте первый и последний элементы в списке. Используемый метод сортировки будет получен с языка программирования, который я использую.

Какой вариант правильный? Если нет, какова будет лучшая стратегия? Я использую Java для написания тестов, но этот вопрос больше сосредоточен на том, как писать тестовый метод, а не использовать технологию/фрейм. Кроме того, я не могу изменить запрос, чтобы добавить предложение ORDER BY (что облегчит мою работу, но не выполнимо).

Я обеспокоен лучшей практикой. Я думал о сортировке данных, поэтому я буду делать утверждения по двум элементам, но потом я беспокоюсь, если мне также придется протестировать Comparator, используемые для сортировки, потому что он может сортировать список неправильно, и мой тест не удастся, проверяя каждый элемент вручную означает использование операторов if-else для утверждений, и я не уверен, что это хорошая практика.

Ответ 1

Я вижу, как ваша главная проблема состоит в том, чтобы написать unit test с самой простой логикой. Это приведет к повышению уровня доверия, когда unit test сообщает об успехе или неудаче, что действительно означает, что запрос возвращает хорошие или плохие результаты, а не то, что вы закодировали ошибку в логике вашего unit test. Для вас даже не может быть безупречной производительности.

Если это ваш случай, я предлагаю использовать ваш очень прямой вариант # 1, где вы просто проверяете каждую дату/время последовательно и не выполняете unit test, как только вы сталкиваетесь с датой/временем, которое не находится в пределах минимальная/максимальная дата/время. Но я бы скорректировал метод сравнения двух наборов даты/времени следующим образом, чтобы логика сравнения была очень простой:

Объединить и форматировать каждую дату/время в следующий формат строки: YYYY-MM-DD hhmm (например: 2015-01-01 0700). Другими словами, ваша строка отформатирована с нулевым дополнением, так что она всегда будет иметь длину 15. После этого формата точно есть очень удобное свойство, которое, если вы сравните две такие строки с использованием встроенного метода String.compareTo(), будет точно сравнивать ваши даты.

Это позволяет вам сохранить вашу логику очень простой и удобочитаемой. Вот пример того, как это могло бы выглядеть (вы не указали, поэтому я предполагаю, что ваша дата - это строка, а время - число, но вы можете приспособиться к вашим фактическим типам):

// starting boundary values
String dateFrom = "2015-01-01";
int hourFrom = 700;
String dateTo = "2015-01-03";
int hourTo = 600;

String formatString = "%s %04d"; // adjust as necessary.

String fromDateTime = String.format(formatString, dateFrom, hourFrom);
String toDateTime = String.format(formatString, dateTo, hourTo);

// execute query here

while (rs.next()) {
    String dateTime = String.format(formatString, rs.getString("date"), rs.getInt("hour"));

    if (fromDateTime.compareTo(dateTime) > 0 || toDateTime.compareTo(dateTime) < 0) {
        throw new Exception("fail unit test");
    }
}

Ответ 2

Оба варианта, которые вы предложили, верны. Опция, в которой вы сортируете данные, будет проще реализовать.

Ответ 3

Нет ничего плохого в сортировке результатов после их извлечения. Это подход, который я бы взял, но проверка каждой строки также будет работать.

Ответ 4

Поскольку это Date, лучше использовать java-объекты Date,

import java.io.IOException;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class ATest {

    public static void main(String[] args) throws IOException, ParseException {
        String dateFrom = "2015-01-01";
        String dateTo = "2015-01-03";

        // those are actually string as i see.
        String hourFrom = "700";
        String hourTo = "600";


        Date from = str2Date(dateFrom, hourFrom);
        Date to = str2Date(dateTo, hourTo);

        Date any = new GregorianCalendar().getTime();

        // now testing any date using 'before' 'after'
        assert(any.after(from) && any.before(to));

        // or using compareTo
        assert(any.compareTo(from) > 0 && any.compareTo(to) < 0);

        // or simpy comparing epocs, i would use this
        long low = from.getTime();
        long high = from.getTime();

        assert( any.getTime() > low && any.getTime() < high);
    }

    private static Date str2Date(String date_input, String time_input) {

        // probably this is an overkill.
        while (time_input.length() < 4){
            time_input = "0" + time_input;
        }

        String parts[] = date_input.split("-");
        int year = Integer.parseInt(parts[0]); 
        int month = Integer.parseInt(parts[1]); 
        int date = Integer.parseInt(parts[2]);

        int hourOfDay = Integer.parseInt(time_input.subSequence(0, 2).toString()); 
        int minute = Integer.parseInt(time_input.subSequence(2, 4).toString());  
        int second = 0;

        Calendar cal = GregorianCalendar.getInstance();
        cal.set(year, month - 1, date, hourOfDay, minute, second);

        return cal.getTime();
    }
}

Сортировка или нет для меня не важна (если количество элементов в списке не очень велико).

Ответ 5

Go с опцией 1. По мере прохождения данных запишите максимальные и минимальные значения. Один раз можно переходить только по списку. Если ваша цель состоит в том, чтобы найти существование несовместимых данных, тогда возможно, что вы не можете завершить обход до конца, если вы уже нашли его. Это более эффективно, чем сортировка списка. В худшем случае O (n).