2015-08-13 31 views
10

我正在測試查詢的結果。其中,結果存儲在表中有這樣的結構:可以在測試用例的主體中對List進行排序以檢查邊界數據嗎?

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...) 

和查詢,以做到基於DateHour列這樣的搜索接收參數:

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

例如,如果我使用以下值:

  • dateFrom: '2015年1月1日'
  • hourFrom:700
  • dateTo: '2015年1月3日'
  • hourTo:600

查詢將返回所有行,其中的Date值爲2015-01-012015-01-03之間,的hour的值是對於Date = 2015-01-01僅高於或等於700,對於Date = 2015-01-03hour的值低於或等於600。在此示例中,將從數據源中檢索所有包含Date = 2015-01-02的行。

我在列表中檢索查詢的執行結果。爲了評估結果,我使用了我用來檢查列表中的數據是否符合它們的參數的值。我正在使用一種方法來檢查元素的日期是否在dateFromdateTo之間,但我想知道如何測試hourFromhourTo的值。我有以下觀點:

  • 開始爲hour在哪裏的Date值是元素的最少值進行覈對等於我dateFrom參數,並檢查該值等於hourFrom。對於hourTo執行類似的操作,但對於Date值等於dateTo參數值的那些行的最大值。
  • 將我的測試方法中的列表按DateHour排序,然後檢查列表中的第一個和最後一個元素。要使用的排序方法將從我正在使用的編程語言中獲得。

哪個選項是正確的?如果沒有,那麼最好的策略是什麼?我使用Java編寫測試,但是這個問題更關注於如何編寫測試方法,而不是要使用的技術/框架。另外,我無法修改查詢來添加ORDER BY子句(這會減輕我的工作量,但不可行)。

我很關心最佳實踐。我正在考慮對數據進行排序,所以我會對兩個元素進行斷言,但是我擔心如果我還需要測試用於排序的Comparator,因爲它可能會錯誤地對列表進行排序,並且我的測試將失敗,同時手動檢查每個元素意味着使用if-else聲明來聲明斷言,我不確定這是否是一種好的做法。

回答

7

我可以看到你的主要關注點是如何用最簡單的邏輯編寫單元測試。這樣做會提高你的置信度,當單元測試報告成功或失敗時,它確實意味着查詢返回好的或壞的結果,而不是你在單元測試的邏輯中編寫了錯誤。獲得絕對最佳表現對你而言可能無關緊要。

如果這是您的情況,我建議您使用您的非常簡單的選項#1,在這裏您只需按順序檢查每個日期/時間,並在遇到不在日期/時間內的情況下儘快通過單元測試您的最小/最大日期/時間。但我會按以下方式調整比較2組日期/時間的方法,以保持比較邏輯非常簡單:

將每個日期/時間連接並格式化爲以下字符串格式: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"); 
    } 
} 
+0

這似乎很有趣,比我目前的想法更有用。我明天會測試這個(現在是星期日晚上8點),並會告訴你它是如何發生的。謝謝。 –

2

你提出的兩個選項都是正確的。對數據進行排序的選項將更容易實現。

2

檢索結果後排序結果沒有任何問題。這是我會採取的方法,但檢查每一行也會起作用。

-1

轉到選項1.在遍歷數據時,記錄最大值和最小值。你只能遍歷一次列表。如果你的目標只是爲了找到不合規數據的存在,那麼如果你已經找到一個數據,你可能不會完成遍歷。這比排序列表更有效。最壞的情況是O(n)。

2

既然是日期,最好使用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(); 
    } 
} 

排序與否對我來說並不重要(如果列表中的元素數量不是很高)。

相關問題