在用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