【发布时间】:2013-07-16 15:46:38
【问题描述】:
我正在实现一些基本的排序算法(出于学习的目的),并想为它们编写单元测试。所有排序程序都有以下通用api
...
public static void sort(Comparable[] a);
...
public static boolean isSorted(Comparable[] a);
...
public static boolean isSorted(Comparable[] a),int from ,int to;
...
所以,我编写了以下测试来测试 SelectionSort 中的 isSorted() 方法
public class SelectionSortTests {
String[] a ;
@After
public void tearDown() throws Exception {
a = null;
}
@Test
public void arraySortedSingleElement(){
a = new String[]{"A"};
Assert.assertTrue(SelectionSort.isSorted(a));
}
@Test
public void arraySortedDistinctElements(){
a = new String[]{"A","B","C","D"};
Assert.assertTrue(SelectionSort.isSorted(a));
}
@Test
public void arrayNotSorted(){
a = new String[]{"A","B","C","B"};
Assert.assertFalse(SelectionSort.isSorted(a));
}
...
}
现在我觉得如果我要为说 InsertionSort、ShellSort 等编写测试,它们看起来会一样..只有被测试类的名称会改变..
那么,我应该如何组织测试呢?套件是答案还是我可以使用反射做得更好 - 可以编写一个驱动程序,我可以向其中添加要测试的类的名称列表,并且驱动程序调用通过将类名传递给它来运行公共单元测试。 .
我意识到这是一种常见的情况..想知道如何在没有唾沫或玻璃纸的情况下处理这种情况
更新: 感谢@BevinQ 和@Matthew Farwell,我尝试使用参数化单元测试来解决这个问题。 使用反射调用静态方法.. 似乎工作:) 虽然我认为它仍然可以重构以避免重复代码
@RunWith(Parameterized.class)
public class ParameterizedSortTests {
private Class classToTest;
private Method methodToTest;
public ParameterizedSortTests(String packageName,String classToTest) {
super();
try {
this.classToTest = Class.forName(packageName+"."+classToTest);
} catch (ClassNotFoundException e) {
System.out.println("failed to get class!!");
e.printStackTrace();
}
}
//method return collection of class names to be tested
@Parameterized.Parameters
public static List<Object[]> classesToTest(){
return Arrays.asList(new Object[][]{
{"elemsorts","SelectionSort"} ,
{"elemsorts","InsertionSort"}
});
}
public void setMethod(String method,Class...args){
try {
this.methodToTest = this.classToTest.getMethod(method, args);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
@Test
public void arrayIsSorted(){
setMethod("isSorted",Comparable[].class);
String[] a = new String[]{"A","B","C","D"};
Boolean arraySorted = null;
try {
arraySorted = (Boolean)this.methodToTest.invoke(null, new Object[]{a});
System.out.println(this.methodToTest+"returned :"+arraySorted);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Assert.assertTrue(arraySorted);
}
@Test
public void arrayIsNotSorted(){
setMethod("isSorted",Comparable[].class);
String[] a = new String[]{"A","B","C","B"};
Boolean arraySorted = null;
try {
arraySorted = (Boolean)this.methodToTest.invoke(null, new Object[]{a});
System.out.println(this.methodToTest+"returned :"+arraySorted);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//System.out.println("arraySorted="+arraySorted);
Assert.assertFalse(arraySorted);
}
}
【问题讨论】:
-
困难在于使您的方法静态化。如果您要使它们不是静态的并实现一个接口。你会发现生活轻松多了。如果你想要一些结构,你将不得不使用反射来调用方法。
标签: java junit organization