在用Java編寫的大中型開源項目中,我們收到許多錯誤報告,針對這些錯誤報告的單元測試更少,以及更少的關閉這些錯誤的補丁。瞭解@ Ignore'd測試何時傳遞
當提供單元測試但未提供補丁時,我們通過將測試功能添加到套件來驗證是否存在針對幹線的缺陷。我們承諾它,但添加一個註釋,以免打破已知bug的構建。
一些錯誤可能是相關的,或者對一個錯誤所做的更改可能會修復另一個錯誤。我們想知道以前已知失敗的測試用例何時不再失敗,因此我們可以通知觀看該錯誤並關閉錯誤的人員。
比方說,我們有一些越野車功能 - 引發異常,有意外的副作用,或返回錯誤的值。 (Real world example)
public void buggyFunction() {
throw new UnsupportedOperationException("this will be implemented later");
}
而一些單元測試,以測試buggyFunction
@Test
public void knownIssue() {
buggyFunction();
}
選項1:@Ignore
測試
@Ignore("this test is currently failing. see bug 12345")
@Test
public void knownIssue() {
buggyFunction();
}
選項2:標準junit4方式是使用@Test(expected=MyException.class)
或撒上@Rule
ExpectedException
s整個測試功能。也不要給用戶一個有用的信息,說明爲什麼一個失敗的測試意味着一個錯誤已經修復,並且更新單元測試並關閉錯誤。另外,如果拋出期望的異常,則測試通過,但在這種情況下測試沒有意義。如果失敗(錯誤修復時)或跳過(當錯誤仍然打開時)會更好。
// when this bug is fixed, it should not throw an exception
// TODO: delete expected=UnsupportedOperationException.class
@Test(expected=UnsupportedOperationException.class)
public void knownIssue() {
buggyFunction();
}
OR
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public void knownIssue() {
thrown.expect(UnsupportedOperationException.class);
thrown.expectMessage("this will be implemented later");
buggyFunction();
thrown.expect(ExpectedException.none());
}
選項3:布格了鍋爐板腳手架測試
@Test
public void knownIssue() {
try {
buggyFunction();
} catch (UnsupportedOperationException e) {
// we know that buggyFunction is broken, so skip this test
assumeTrue("Skipping test. Expected exception: " + e, false);
}
// surprise! buggyFunction isn't broken anymore!
fail("The function is no longer buggy! " +
"Update the unit test and close bug 12345!");
}
是否有沒有更好的方法是:
- 做當已知的問題是開放
- 通知我們,當一個已知的問題是
- 優選的是,作爲已知的問題是開放的,只要算作一個跳過測試
- 最好,亂the-不破壞構建從Hamcrest或其他庫的框解決方案
我可以在Python中非常容易地完成這樣的事情,其中未評估函數是第一類對象。在Java 6中也可以做到這一點(是的,這是我們正在使用的版本),但可能需要比選項3更多的樣板。請告訴我我錯了。
def alertWhenFixed(expected=Exception, bug=12345):
def decorator(func):
def func_wrapper(*args, **kwargs):
try:
func(*args, **kwargs)
except Exception as e:
if isinstance(e, expected):
assumeTrue("Skipping test. Expected exception: {}"
.format(e), false)
else:
raise e
fail("The function is no longer buggy! " +
"Update the unit test and close bug {}".format(bug))
return func_wrapper
return decorator
@alertWhenFixed(expected=UnsupportedOperationException, bug=12345)
def knownIssue():
buggyFunctionThrowsException()
@alertWhenFixed(expected=AssertionFailed)
def knownIssue():
assertEquals(42, buggyFunctionReturnsWrongValue())
@alertWhenFixed(expected=AssertionFailed)
def knownIssue():
buggyFunctionHasWrongSideEffect()
assertEquals(42, getSideEffect())
此修飾器可以測試引發異常,返回錯誤值或產生錯誤副作用的已知問題。
這個裝飾器是100%可重用的,所以沒有複製麪食嘗試/除了腳手架,我可以刪除一行代碼,當已知問題已修復時,最重要的是我可以離開測試案例邏輯。
任何想法,如果這可以被翻譯成Java 6或7?
以我的經驗,最好的方法是不要放棄忽略,不要指望Exception,不要添加try catch,而是要解決實際問題。 – Stultuske
@Stultuske這是一個很好的主意,顯然每個人都會同意。但在現實世界中,特別是在大型組織和大型項目中,事情並不那麼簡單。或者你真的認爲他會寫這個冗長的問題,如果他會談論他可以在此期間修復的兩個錯誤?! – GhostCat
@GhostCat你的意思是你認爲將產品投入生產是可以接受的,因爲知道其中存在缺陷,因爲你有可能忽略測試嗎? – Stultuske