📄 tij317.htm
字号:
<font color=#009900>// tearDown() is also optional, and is called after</font>
<font color=#009900>// each test. setUp() and tearDown() can be either</font>
<font color=#009900>// protected or public:</font>
<font color=#0000ff>public</font> <font color=#0000ff>void</font> tearDown() {
System.out.println(<font color=#004488>"Tearing down "</font> + list.getId());
}
<font color=#009900>// All tests have method names beginning with "test":</font>
<font color=#0000ff>public</font> <font color=#0000ff>void</font> testInsert() {
System.out.println(<font color=#004488>"Running testInsert()"</font>);
assertEquals(list.size(), 3);
list.add(1, <font color=#004488>"Insert"</font>);
assertEquals(list.size(), 4);
assertEquals(list.get(1), <font color=#004488>"Insert"</font>);
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> testReplace() {
System.out.println(<font color=#004488>"Running testReplace()"</font>);
assertEquals(list.size(), 3);
list.set(1, <font color=#004488>"Replace"</font>);
assertEquals(list.size(), 3);
assertEquals(list.get(1), <font color=#004488>"Replace"</font>);
}
<font color=#009900>// A "helper" method to reduce code duplication. As long</font>
<font color=#009900>// as the name doesn't start with "test," it will not</font>
<font color=#009900>// be automatically executed by JUnit.</font>
<font color=#0000ff>private</font> <font color=#0000ff>void</font> compare(ArrayList lst, String[] strs) {
Object[] array = lst.toArray();
assertTrue(<font color=#004488>"Arrays not the same length"</font>,
array.length == strs.length);
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < array.length; i++)
assertEquals(strs[i], (String)array[i]);
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> testOrder() {
System.out.println(<font color=#004488>"Running testOrder()"</font>);
compare(list, <font color=#0000ff>new</font> String[] { <font color=#004488>"0"</font>, <font color=#004488>"1"</font>, <font color=#004488>"2"</font> });
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> testRemove() {
System.out.println(<font color=#004488>"Running testRemove()"</font>);
assertEquals(list.size(), 3);
list.remove(1);
assertEquals(list.size(), 2);
compare(list, <font color=#0000ff>new</font> String[] { <font color=#004488>"0"</font>, <font color=#004488>"2"</font> });
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> testAddAll() {
System.out.println(<font color=#004488>"Running testAddAll()"</font>);
list.addAll(Arrays.asList(<font color=#0000ff>new</font> Object[] {
<font color=#004488>"An"</font>, <font color=#004488>"African"</font>, <font color=#004488>"Swallow"</font>}));
assertEquals(list.size(), 6);
compare(list, <font color=#0000ff>new</font> String[] { <font color=#004488>"0"</font>, <font color=#004488>"1"</font>, <font color=#004488>"2"</font>,
<font color=#004488>"An"</font>, <font color=#004488>"African"</font>, <font color=#004488>"Swallow"</font> });
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
<font color=#009900>// Invoke JUnit on the class:</font>
junit.textui.TestRunner.run(JUnitDemo.<font color=#0000ff>class</font>);
monitor.expect(<font color=#0000ff>new</font> String[] {
<font color=#004488>"CountedList #0"</font>,
<font color=#004488>"CountedList #1"</font>,
<font color=#004488>"CountedList #2"</font>,
<font color=#004488>"CountedList #3"</font>,
<font color=#004488>"CountedList #4"</font>,
<font color=#009900>// '.' indicates the beginning of each test:</font>
<font color=#004488>".Set up for 0"</font>,
<font color=#004488>"Running testInsert()"</font>,
<font color=#004488>"Tearing down 0"</font>,
<font color=#004488>".Set up for 1"</font>,
<font color=#004488>"Running testReplace()"</font>,
<font color=#004488>"Tearing down 1"</font>,
<font color=#004488>".Set up for 2"</font>,
<font color=#004488>"Running testOrder()"</font>,
<font color=#004488>"Tearing down 2"</font>,
<font color=#004488>".Set up for 3"</font>,
<font color=#004488>"Running testRemove()"</font>,
<font color=#004488>"Tearing down 3"</font>,
<font color=#004488>".Set up for 4"</font>,
<font color=#004488>"Running testAddAll()"</font>,
<font color=#004488>"Tearing down 4"</font>,
<font color=#004488>""</font>,
<font color=#004488>"%% Time: .*"</font>,
<font color=#004488>""</font>,
<font color=#004488>"OK (5 tests)"</font>,
<font color=#004488>""</font>,
});
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>To set up unit testing, you must only <b>import junit.framework.*</b> and extend <b>TestCase</b>, as <b>JUnitDemo</b> does. In addition, you must create a constructor that takes a <b>String</b> argument and passes it to its <b>super</b> constructor. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0198" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>For each test, a new <b>JUnitDemo </b>object will be created, and thus all the non-<b>static </b>members will also be created. This means a new <b>CountedList</b> object (<b>list</b>)<b> </b>will be created and initialized for each test, since it is a field of <b>JUnitDemo</b>. In addition, the constructor will be called for each test, so <b>list</b> will be initialized with the strings “0”, “1”, and “2” before each test is run. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0199" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>To observe the behavior of <b>setUp( ) </b>and <b>tearDown( )</b>, these methods are created to display information about the test that’s being initialized or cleaned up. Note that the base-class methods are <b>protected</b>, so the overridden methods may be either <b>protected</b> or <b>public</b>. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0200" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p><b>testInsert( )</b> and <b>testReplace( )</b> demonstrate typical test methods, since they follow the required signature and naming convention. JUnit discovers these methods using reflection and runs each one as a test. Inside the methods, you perform any desired operations and use JUnit assertion methods (which all start with the name “assert”) to verify the correctness of your tests (the full range of “assert” statements can be found in the JUnit javadocs for <b>junit.framework.Assert</b>). If the assertion fails, the expression and values that caused the failure will be displayed. This is usually enough, but you can also use the overloaded version of each JUnit assertion statement and include a <b>String</b> that will be printed if the assertion fails. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0201" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The assertion statements are not required; you can also just run the test without assertions and consider it a success if no exceptions are thrown. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0202" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The <b>compare( )</b> method is an example of a “helper” method that is not executed by JUnit but instead is used by other tests in the class. As long as the method name doesn’t begin with “test,” JUnit doesn’t run it or expect it to have a particular signature. Here, <b>compare( )</b> is <b>private</b> to emphasize that it is only used within the test class, but it could also be public. The remaining test methods eliminate duplicate code by refactoring it into the <b>compare( )</b> method. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0012" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>To execute the JUnit tests, the static method <b>TestRunner.run( )</b> is invoked in <b>main( )</b>. This method is handed the class that contains the collection of tests, and it automatically sets up and runs all the tests. From the <b>expect( )</b> output, you can see that all the objects needed to run all the tests are created first, in a batch—this is where the construction happens.<sup><a name="fnB92" href="#fn92">[92]</a></sup> Before each test, the <b>setUp( )</b> method is called. Then the test is run, followed by the <b>tearDown( )</b> method. JUnit demarcates each test with a ‘<b>.</b>’. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0013" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Although you can probably survive easily by only using the simplest approach to JUnit as shown in the preceding example, JUnit was originally designed with a plethora of complicated structures. If you are curious, you can easily learn more about them, because the JUnit download from <i>www.JUnit.org</i> comes with documentation and tutorials. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0197" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h2>
<a name="_Toc24775935"></a><a name="Heading22814"></a>Improving reliability with
assertions<br></h2>
<p><a name="Index2022"></a><a name="Index2023"></a><i>Assertions</i>, which you’ve seen used in earlier examples in this book, were added to the JDK 1.4 version of Java in order to aid programmers in improving the reliability of their programs. Properly used, assertions can add to program robustness by verifying that certain conditions are satisfied during the execution of your program. For example, suppose you have a numerical field in an object that represents the month on the Julian calendar. You know that this value must always be in the range 1-12, and an assertion can be used to check this and report an error if it somehow falls outside of that range. If you’re inside a method, you can check the validity of an argument with an assertion. These are important tests to make sure that your program is correct, but they cannot be performed by compile-time checking, and they do not fall into the purview of unit testing. In this section, we’ll look at the mechanics of the assertion mechanism, and the way that you can use assertions to partially implement the <i>design by contract</i> concept. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0208" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc24775936"></a><a name="Heading22816"></a>Assertion syntax</h3>
<p>Since you can simulate the effect of assertions using other programming constructs, it can be argued that the whole point of adding assertions to Java is that they are easy to write. Assertion statements come in two forms: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0209" title="Send BackTalk Comment">Feedback</a></font><br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>assert <font color=#0000ff>boolean</font>-expression;
assert <font color=#0000ff>boolean</font>-expression: information-expression;</PRE></FONT></BLOCKQUOTE><p><br></p>
<p>Both of these statements say “I assert that the boolean-expression will produce a <b>true</b> value.” If this is not the case, the assertion will produce an <b>AssertionError</b> exception. This is a <b>Throwable</b> subclass, and as such doesn’t require an exception specification. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0210" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Unfortunately, the first form of assertion does <i>not</i> produce any information containing the boolean-expression in the exception produced by a failed assertion (in contrast with most other languages’ assertion mechanisms). Here’s an example showing the use of the first form: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0211" title="Send BackTalk Comment">Feedback</a></font><br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c15:Assert1.java</font>
<font color=#009900>// Non-informative style of assert</font>
<font color=#009900>// Compile with: javac -source 1.4 Assert1.java</font>
<font color=#009900>// {JVMArgs: -ea} // Must run with -ea</font>
<font color=#009900>// {ThrowsException}</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Assert1 {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
assert <font color=#0000ff>false</font>;
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>Assertions are turned off in JDK 1.4 by default (this is annoying, but the designers managed to convince themselves it was a good idea). To prevent compile-time errors, you must compile with the flag: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0212" title="Send BackTalk Comment">Feedback</a></font><br></p>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>-source 1.4</PRE></FONT></BLOCKQUOTE><p><br></p>
<p>If you don’t use this flag, you’ll get a chatty message saying that <b>assert</b> is a keyword in JDK 1.4 and cannot be used as an identifier anymore. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]A0213" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>If you just run the program the way you normally do, without any special assertion flags, nothing will happen. You must enable assertions when you run the program. The easiest way to do this is with the <b>-ea</b> flag, but
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -