测试工作(1.1 -- 补Junit3执行流程)

补:Junit3执行流程分析

1、TestRunner 入口点。生成TestRunner实例,首先执行TestRunner的main方法。

public static void main(String args[]) {
		TestRunner aTestRunner= new TestRunner(); 
		try {
			//args参数指定的测试类的名称
			TestResult r= aTestRunner.start(args);
		} catch(Exception e) {}
}


2、构造生成TestSuite 。suite的概念在于,一个测试类存在多个测试方法,将所有的测试方法抽取存储于一个集合,遍历执行对应操作。
/**
* Starts a test run. Analyzes the command line arguments and runs the given
* test suite.
*/
	public TestResult start(String args[]) throws Exception {
		String testCase= args[i]; // 赋值“测试类”名称
		String method= "";
		boolean wait= false;
		try {
			//判断是否执行单个方法的测试
			if (!method.equals("")) 
				return runSingleMethod(testCase, method, wait);
			//构造生成TestSuite
			Test suite= getTest(testCase);
			//执行测试
			return doRun(suite, wait);
		} catch (Exception e) {}
}


3、TestRunner继承BaseTestRunner,getTest()是BaseTestRunner定义的一个模版方法
/**
* Returns the Test corresponding to the given suite. This is
* a template method, subclasses override runFailed(), clearStatus().
*/
	public Test getTest(String suiteClassName) {
		Class testClass= null;
		try {
			//根据类名加载“测试类”
			testClass= loadSuiteClass(suiteClassName);
		} catch (ClassNotFoundException e) {} 
		  catch(Exception e) {}
		Method suiteMethod= null;
		try {
			//Junit3中可以自定义suite()方法,根据反射尝试获取suite方法对于的Method类
			suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]);
	 	} catch(Exception e) {
	 		// try to extract a test suite automatically
			clearStatus();
			//若不存在suite方法,则构造Junit自动构造测试方法集合suite,返回。
			return new TestSuite(testClass);
		}
	}



4、正式构造TestSuite
/**
* Constructs a TestSuite from the given class. Adds all the methods
* starting with "test" as test cases to the suite.
*/
	 public TestSuite(final Class theClass) {
		fName= theClass.getName();
		Class superClass= theClass;
		Vector names= new Vector();
		//遍历方法,判断是否为“需要测试”方法,构造
		while (Test.class.isAssignableFrom(superClass)) {
			Method[] methods= superClass.getDeclaredMethods();
			for (int i= 0; i < methods.length; i++) {
				addTestMethod(methods[i], names, theClass);
			}
			//获取到“父”类,一层层的向上遍历,找寻“Test”方法,添加到TestSuite
			superClass= superClass.getSuperclass();
		}
		if (fTests.size() == 0)
			addTest(warning("No tests found in "+theClass.getName()));
	}

private void addTestMethod(Method m, Vector names, Class theClass) {
		String name= m.getName();
		//判断出来,添加进MethodName的集合names
		if (names.contains(name))
			return;
		if (! isPublicTestMethod(m)) {
			if (isTestMethod(m))
				addTest(warning("Test method isn't public: "+m.getName()));
			return;
		}
		names.addElement(name);
		// createTest()根据 theClass与name(即方法名),为每个方法构造独立的TestCase的实例,指定TestCase的fName为name值,存储此TestCase于TestSuite
		//就是说 :一个类有很多的需要测试方法,为每一个测试方法生成一个自身的实例,向上转型为TestCase,给TestCase的属性fName赋值为对应测试方法的名称
		addTest(createTest(theClass, name));
	}



5、准备执行测试
public TestResult doRun(Test suite, boolean wait) {
		TestResult result= createTestResult(); //TestResult存储所有的执行结果信息
		result.addListener(fPrinter); //添加监听器
		long startTime= System.currentTimeMillis();
		suite.run(result); //实际执行
		long endTime= System.currentTimeMillis();
		long runTime= endTime-startTime;
		fPrinter.print(result, runTime);
		return result;
}



6、开始执行
/**
* Runs the tests and collects their result in a TestResult.
*/
	public void run(TestResult result) {
		//遍历执行所有的测试
		for (Enumeration e= tests(); e.hasMoreElements(); ) {
	  		if (result.shouldStop() )
	  			break;
			Test test= (Test)e.nextElement();
			runTest(test, result);
		}
	}

/**
* Runs the bare test sequence.
* @exception Throwable if any exception is thrown
*/
	public void runBare() throws Throwable {
		Throwable exception= null;
		setUp(); //每个测试方法执行前执行的setUp()
		try {
			runTest(); //执行测试方法
		} catch (Throwable running) {
			exception= running;
		}
		finally {
			try {
				tearDown();//tearDown写在finally不论怎么样,在测试执行结束都会执行
			} catch (Throwable tearingDown) {
				if (exception == null) exception= tearingDown;
			}
		}
		if (exception != null) throw exception;
	}



7、通过反射执行实际的测试方法
/**
* Override to run the test and assert its state.
* @exception Throwable if any exception is thrown
*/
	protected void runTest() throws Throwable {
		assertNotNull(fName); // Some VMs crash when calling
		Method runMethod= null;
		try {
			// use getMethod to get all public inherited
			// methods. getDeclaredMethods returns all
			// methods of this class but excludes the
			// inherited ones.
			//根据反射取得对应方法的Method类
			runMethod= getClass().getMethod(fName, (Class[])null);
		} catch (NoSuchMethodException e) {}

		try {
			//通过反射实际执行测试方法
			runMethod.invoke(this, (Object[])new Class[0]);
		}
		catch (InvocationTargetException e) {}
	}



8、实际的测试方法
public void testAdd() {
		Arithmetic a = new Arithmetic();
		int expected = 3;
		assertEquals("失败", expected, a.add(1, 2));
	}



9、执行Assert
/**
* Asserts that two ints are equal. If they are not
* an AssertionFailedError is thrown with the given message.
*/
  	static public void assertEquals(String message, int expected, int actual) {
		assertEquals(message, new Integer(expected), new Integer(actual));
  	}


10、最终的错误的捕捉,以及测试结果打印。通过TestResult实现。


总结 :觉得和很多人说的那样,Junit更多体现的是优秀的设计思想。可惜自己现在还没有领悟到这步,只能简单的对整个的执行流程有初步的认识。继续努力。

你可能感兴趣的:(工作,JUnit)