是否可以在测试用例的主体中对列表进行排序以检查边界数据?
Is it ok to sort a List in the body of the test case to check for boundary data?
我正在测试查询的结果。存储结果的 table 结构如下:
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's no ORDER BY clause in the query
例如,如果我使用以下值:
dateFrom
: '2015-01-01'
hourFrom
: 700
dateTo
: '2015-01-03'
hourTo
: 600
查询将 return 所有 Date
的值在 2015-01-01
和 2015-01-03
之间的行,hour
的值大于或等于仅 Date = 2015-01-01
小于 700,hour
的值小于或等于 Date = 2015-01-03
的 600。在此示例中,将从数据源中检索所有具有 Date = 2015-01-02
的行。
我在列表中检索执行查询的结果。为了评估结果,我使用了我用来检查列表中的数据是否符合它们的参数值。我正在使用一种方法来检查元素的日期是否在 dateFrom
和 dateTo
之间,但我想知道如何测试 hourFrom
和 [=17= 的值].我有以下想法:
- 开始检查
Date
的值等于我的 dateFrom
参数的元素的 hour
的最小值,并检查该值是否等于 hourFrom
.对 hourTo
执行类似操作,但使用那些行的最大值,其中 Date
的值等于 dateTo
参数值。
- 在我的测试方法中按
Date
和 Hour
对列表进行排序,然后检查列表中的第一个和最后一个元素。要使用的排序方法将从我正在使用的编程语言中获得。
哪个选项是正确的?如果 none,最好的策略是什么?。我正在使用 Java 来编写测试,但这个问题更侧重于如何编写测试方法而不是 technology/framework 来使用。此外,我无法修改查询以添加 ORDER BY
子句(这会减轻我的很多工作但不可行)。
我担心最佳实践。我正在考虑对数据进行排序,因此我将对两个元素进行断言,但是我担心我是否还必须测试用于排序的 Comparator
因为它可能会错误地对列表进行排序并且我的测试将失败,而手动检查每个元素意味着对断言使用 if-else
语句,我不确定这是否是一个好习惯。
您提出的两个选项都是正确的。对数据进行排序的选项将更容易实现。
检索结果后对结果进行排序没有错。这是我会采用的方法,但检查每一行也可以。
选择选项 1。遍历数据时,记录最大值和最小值。您只能遍历列表一次。如果你的objective只是为了找到不符合条件的数据的存在,那么你已经找到了可能还没有遍历到最后。这比对列表排序更有效。最坏的情况是 O(n).
我明白您最关心的可能是用尽可能简单的逻辑编写单元测试。这样做会提高您的信心水平,即当单元测试报告成功或失败时,这确实意味着查询返回了好的或坏的结果,而不是您在单元测试的逻辑中编码了错误。拥有绝对最好的性能对你来说甚至都无关紧要。
如果是这种情况,我建议使用非常直接的选项 #1,您只需按顺序检查每个 date/time,并在遇到 [=23= 时立即使单元测试失败] 不在您的 min/max date/time 之内。但是我会通过以下方式调整比较 2 组 date/time 的方法,以保持比较逻辑非常简单:
将每个 date/time 连接并格式化为以下字符串格式:YYYY-MM-DD hhmm
(例如:2015-01-01 0700
)。换句话说,您的字符串使用所需的零填充进行格式化,因此它的长度始终为 15
。遵循这种格式恰恰有一个非常方便的 属性,如果您使用内置的 String.compareTo()
方法比较 2 个这样的字符串,它会准确地比较您的日期。
这样可以让您的逻辑非常简单和可读。这是一个例子(你没有指定,所以我假设你的日期是一个字符串,时间是一个数字。但是你可以根据你的实际类型进行调整):
// 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");
}
}
既然是日期,最好使用java日期对象;
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();
}
}
排序与否对我来说并不重要(如果列表中的元素数量不是很多)。
我正在测试查询的结果。存储结果的 table 结构如下:
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's no ORDER BY clause in the query
例如,如果我使用以下值:
dateFrom
: '2015-01-01'hourFrom
: 700dateTo
: '2015-01-03'hourTo
: 600
查询将 return 所有 Date
的值在 2015-01-01
和 2015-01-03
之间的行,hour
的值大于或等于仅 Date = 2015-01-01
小于 700,hour
的值小于或等于 Date = 2015-01-03
的 600。在此示例中,将从数据源中检索所有具有 Date = 2015-01-02
的行。
我在列表中检索执行查询的结果。为了评估结果,我使用了我用来检查列表中的数据是否符合它们的参数值。我正在使用一种方法来检查元素的日期是否在 dateFrom
和 dateTo
之间,但我想知道如何测试 hourFrom
和 [=17= 的值].我有以下想法:
- 开始检查
Date
的值等于我的dateFrom
参数的元素的hour
的最小值,并检查该值是否等于hourFrom
.对hourTo
执行类似操作,但使用那些行的最大值,其中Date
的值等于dateTo
参数值。 - 在我的测试方法中按
Date
和Hour
对列表进行排序,然后检查列表中的第一个和最后一个元素。要使用的排序方法将从我正在使用的编程语言中获得。
哪个选项是正确的?如果 none,最好的策略是什么?。我正在使用 Java 来编写测试,但这个问题更侧重于如何编写测试方法而不是 technology/framework 来使用。此外,我无法修改查询以添加 ORDER BY
子句(这会减轻我的很多工作但不可行)。
我担心最佳实践。我正在考虑对数据进行排序,因此我将对两个元素进行断言,但是我担心我是否还必须测试用于排序的 Comparator
因为它可能会错误地对列表进行排序并且我的测试将失败,而手动检查每个元素意味着对断言使用 if-else
语句,我不确定这是否是一个好习惯。
您提出的两个选项都是正确的。对数据进行排序的选项将更容易实现。
检索结果后对结果进行排序没有错。这是我会采用的方法,但检查每一行也可以。
选择选项 1。遍历数据时,记录最大值和最小值。您只能遍历列表一次。如果你的objective只是为了找到不符合条件的数据的存在,那么你已经找到了可能还没有遍历到最后。这比对列表排序更有效。最坏的情况是 O(n).
我明白您最关心的可能是用尽可能简单的逻辑编写单元测试。这样做会提高您的信心水平,即当单元测试报告成功或失败时,这确实意味着查询返回了好的或坏的结果,而不是您在单元测试的逻辑中编码了错误。拥有绝对最好的性能对你来说甚至都无关紧要。
如果是这种情况,我建议使用非常直接的选项 #1,您只需按顺序检查每个 date/time,并在遇到 [=23= 时立即使单元测试失败] 不在您的 min/max date/time 之内。但是我会通过以下方式调整比较 2 组 date/time 的方法,以保持比较逻辑非常简单:
将每个 date/time 连接并格式化为以下字符串格式:YYYY-MM-DD hhmm
(例如:2015-01-01 0700
)。换句话说,您的字符串使用所需的零填充进行格式化,因此它的长度始终为 15
。遵循这种格式恰恰有一个非常方便的 属性,如果您使用内置的 String.compareTo()
方法比较 2 个这样的字符串,它会准确地比较您的日期。
这样可以让您的逻辑非常简单和可读。这是一个例子(你没有指定,所以我假设你的日期是一个字符串,时间是一个数字。但是你可以根据你的实际类型进行调整):
// 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");
}
}
既然是日期,最好使用java日期对象;
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();
}
}
排序与否对我来说并不重要(如果列表中的元素数量不是很多)。