Хорошо ли сортировать список в тесте тестового примера, чтобы проверить граничные данные?
Я тестирую результаты запроса. Таблица, в которой хранятся результаты, имеет такую структуру:
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).