查看文章 |
l If you are running your JUnit 4 tests with a JUnit 3.x runner, write a suite() method that uses the JUnit4TestAdapter class to create a suite containing all of your test methods: public static junit.framework.Test suite() { return new junit.framework.JUnit4TestAdapter(SimpleTest.class); }
l Tests can use the objects (variables) in a test fixture, with each test invoking different methods on objects in the fixture and asserting different expected results. Each test runs in its own test fixture to isolate tests from the changes made by other tests. That is, tests don't share the state of objects in the test fixture. Because the tests are isolated, they can be run in any order.
l A related issue is to design for testing. For example, if you have a method that is meant to output to a file, don't pass in a filename, or even a FileWriter. Instead, pass in a Writer. That way you can pass in a StringWriter to capture the output for testing purposes. Then you can add a method (e.g. writeToFileNamed(String filename)) to encapsulate the FileWriter creation.
l How do I test things that must be run in a J2EE container (e.g. servlets, EJBs)? Refactoring J2EE components to delegate functionality to other objects that don't have to be run in a J2EE container will improve the design and testability of the software.
Cactus is an open source JUnit extension that can be used to test J2EE components in their natural environment. l How do I run JUnit using Ant? 1. Define any necessary Ant properties: <property name="src" value="./src" /> <property name="lib" value="./lib" /> <property name="classes" value="./classes" /> <property name="test.class.name" value="com.xyz.MyTestSuite" /> 2. Set up the CLASSPATH to be used by JUnit: <path id="test.classpath"> <pathelement location="${classes}" /> <pathelement location="/path/to/junit.jar" /> <fileset dir="${lib}"> <include name="**/*.jar"/> </fileset> </path> 3. Define the Ant task for running JUnit: <target name="test"> <junit fork="yes" haltonfailure="yes"> <test name="${test.class.name}" /> <formatter type="plain" usefile="false" /> <classpath refid="test.classpath" /> </junit> </target> 4. Run the test: ant test l How do I use Ant to create HTML test reports? 1. Ensure that Ant's optional.jar file is either in your CLASSPATH or exists in your $ANT_HOME/lib directory. 2. Add an ANT property for the directory containing the HTML reports: <property name="test.reports" value="./reports" /> 3. Define the Ant task for running JUnit and generating reports: <target name="test-html"> <junit fork="yes" printsummary="no" haltonfailure="no"> <batchtest fork="yes" todir="${test.reports}" > <fileset dir="${classes}"> <include name="**/*Test.class" /> </fileset> </batchtest> <formatter type="xml" /> <classpath refid="test.classpath" /> </junit>
<junitreport todir="${test.reports}"> <fileset dir="${test.reports}"> <include name="TEST-*.xml" /> </fileset> <report todir="${test.reports}" /> </junitreport> </target> 4. Run the test: ant test-html l How do I organize all test classes in a TestSuite automatically and not use or manage a TestSuite explicitly? There are a number of ways to do this: 1. In Ant, use the junit task and the batchtest element: <junit printsummary="yes" haltonfailure="yes"> ... <batchtest fork="yes"> <fileset dir="${src.dir}"> <include name="**/*Test.java" /> <include name="**/Test*.java" /> </fileset> </batchtest> </junit> Idiomatic naming patterns for unit tests are Test*.java and *Test.java. Documentation and examples are at http://ant.apache.org/manual/OptionalTasks/junit.html.
2. Use the DirectorySuiteBuilder and ArchiveSuiteBuilder (for jar/zip files) classes provided by JUnit-addons project:
DirectorySuiteBuilder builder = new DirectorySuiteBuilder(); builder.setSuffix("Test"); Test suite = builer.suite("/home/project/myproject/tests"); Documentation and examples are at http://junit-addons.sourceforge.net.
3. Write your own custom suite builder.
Have your test classes implement an interface and write a treewalker to load each class in a directory, inspect the class, and add any classes that implement the interface to a TestSuite.
You might only want to do this if you are very uncomfortable with using a naming convention for test classes. Aside from being slow for larger suites, ultimately it's arguable whether it's more effort to follow a naming convention that have test classes implement an interface! |