﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-翠湖月色-随笔分类-软件测试技术</title><link>http://www.blogjava.net/matthew2006/category/17745.html</link><description>No Buddha tree at all,And bright mirror nor.Now nothing at all,How dusts any more ? </description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 15:26:15 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 15:26:15 GMT</pubDate><ttl>60</ttl><item><title>一个简单的Eclipse Junit单元测试</title><link>http://www.blogjava.net/matthew2006/archive/2006/12/03/85185.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sun, 03 Dec 2006 06:49:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/12/03/85185.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/85185.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/12/03/85185.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/85185.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/85185.html</trackback:ping><description><![CDATA[
		<p>1 具体过程:新建一个工程-&gt;新建一个被测试类Car.java-&gt;新建一个JunitTestCase: TestCar.java-&gt;运行测试case:选择run as JUnit Test.<br />2 如下为这两个类的源码:<br />Car.java<br /></p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #008080">1</span>
				<img id="Codehighlighter1_23_113_Open_Image" onclick="this.style.display='none'; Codehighlighter1_23_113_Open_Text.style.display='none'; Codehighlighter1_23_113_Closed_Image.style.display='inline'; Codehighlighter1_23_113_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
				<img id="Codehighlighter1_23_113_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_23_113_Closed_Text.style.display='none'; Codehighlighter1_23_113_Open_Image.style.display='inline'; Codehighlighter1_23_113_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000">   </span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000">   Car   </span>
				<span id="Codehighlighter1_23_113_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.blogjava.net/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_23_113_Open_Text">
						<span style="COLOR: #000000">{   <br /></span>
						<span style="COLOR: #008080">2</span>
						<span style="COLOR: #000000">
								<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        <br /></span>
						<span style="COLOR: #008080">3</span>
						<span style="COLOR: #000000">
								<img id="Codehighlighter1_60_106_Open_Image" onclick="this.style.display='none'; Codehighlighter1_60_106_Open_Text.style.display='none'; Codehighlighter1_60_106_Closed_Image.style.display='inline'; Codehighlighter1_60_106_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
								<img id="Codehighlighter1_60_106_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_60_106_Closed_Text.style.display='none'; Codehighlighter1_60_106_Open_Image.style.display='inline'; Codehighlighter1_60_106_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />
						</span>
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000">   </span>
						<span style="COLOR: #0000ff">int</span>
						<span style="COLOR: #000000">   getWheels()</span>
						<span id="Codehighlighter1_60_106_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.blogjava.net/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_60_106_Open_Text">
								<span style="COLOR: #000000">{   </span>
								<span style="COLOR: #008000">//</span>
								<span style="COLOR: #008000">简单的返回3</span>
								<span style="COLOR: #008000">
										<br />
								</span>
								<span style="COLOR: #008080">4</span>
								<span style="COLOR: #008000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />
								</span>
								<span style="COLOR: #000000">              </span>
								<span style="COLOR: #0000ff">return</span>
								<span style="COLOR: #000000">   </span>
								<span style="COLOR: #000000">3</span>
								<span style="COLOR: #000000">;   <br /></span>
								<span style="COLOR: #008080">5</span>
								<span style="COLOR: #000000">
										<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />          }</span>
						</span>
						<span style="COLOR: #000000">   <br /></span>
						<span style="COLOR: #008080">6</span>
						<span style="COLOR: #000000">
								<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    <br /></span>
						<span style="COLOR: #008080">7</span>
						<span style="COLOR: #000000">
								<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
				<span style="COLOR: #000000">
						<br />
				</span>
				<span style="COLOR: #008080">8</span>
				<span style="COLOR: #000000">
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
		</div>TestCar.java<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080"> 1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">   junit.framework.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;   <br /></span><span style="COLOR: #008080"> 2</span><span style="COLOR: #000000"><img id="Codehighlighter1_79_719_Open_Image" onclick="this.style.display='none'; Codehighlighter1_79_719_Open_Text.style.display='none'; Codehighlighter1_79_719_Closed_Image.style.display='inline'; Codehighlighter1_79_719_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_79_719_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_79_719_Closed_Text.style.display='none'; Codehighlighter1_79_719_Open_Image.style.display='inline'; Codehighlighter1_79_719_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">   </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">   TestCar   </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000">   TestCase   </span><span id="Codehighlighter1_79_719_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_79_719_Open_Text"><span style="COLOR: #000000">{   <br /></span><span style="COLOR: #008080"> 3</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">   </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">   expectedWheels;   <br /></span><span style="COLOR: #008080"> 4</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">   Car   myCar;   <br /></span><span style="COLOR: #008080"> 5</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    <br /></span><span style="COLOR: #008080"> 6</span><span style="COLOR: #000000"><img id="Codehighlighter1_203_237_Open_Image" onclick="this.style.display='none'; Codehighlighter1_203_237_Open_Text.style.display='none'; Codehighlighter1_203_237_Closed_Image.style.display='inline'; Codehighlighter1_203_237_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_203_237_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_203_237_Closed_Text.style.display='none'; Codehighlighter1_203_237_Open_Image.style.display='inline'; Codehighlighter1_203_237_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">   TestCar(String   s)   </span><span id="Codehighlighter1_203_237_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_203_237_Open_Text"><span style="COLOR: #000000">{   <br /></span><span style="COLOR: #008080"> 7</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />          </span><span style="COLOR: #0000ff">super</span><span style="COLOR: #000000">(s);   <br /></span><span style="COLOR: #008080"> 8</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />      }</span></span><span style="COLOR: #000000">   <br /></span><span style="COLOR: #008080"> 9</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    <br /></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img id="Codehighlighter1_282_368_Open_Image" onclick="this.style.display='none'; Codehighlighter1_282_368_Open_Text.style.display='none'; Codehighlighter1_282_368_Closed_Image.style.display='inline'; Codehighlighter1_282_368_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_282_368_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_282_368_Closed_Text.style.display='none'; Codehighlighter1_282_368_Open_Image.style.display='inline'; Codehighlighter1_282_368_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">   </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">   setUp()   </span><span id="Codehighlighter1_282_368_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_282_368_Open_Text"><span style="COLOR: #000000">{   <br /></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />          expectedWheels   </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">;   <br /></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />          myCar   </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">   </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">   Car();   <br /></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />      }</span></span><span style="COLOR: #000000">   <br /></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img id="Codehighlighter1_414_481_Open_Image" onclick="this.style.display='none'; Codehighlighter1_414_481_Open_Text.style.display='none'; Codehighlighter1_414_481_Closed_Image.style.display='inline'; Codehighlighter1_414_481_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_414_481_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_414_481_Closed_Text.style.display='none'; Codehighlighter1_414_481_Open_Image.style.display='inline'; Codehighlighter1_414_481_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">   </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">   Test   suite()   </span><span id="Codehighlighter1_414_481_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_414_481_Open_Text"><span style="COLOR: #000000">{   <br /></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />          </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">     </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">   TestSuite(TestCar.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);   <br /></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />      }</span></span><span style="COLOR: #000000">   <br /></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img id="Codehighlighter1_526_647_Open_Image" onclick="this.style.display='none'; Codehighlighter1_526_647_Open_Text.style.display='none'; Codehighlighter1_526_647_Closed_Image.style.display='inline'; Codehighlighter1_526_647_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_526_647_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_526_647_Closed_Text.style.display='none'; Codehighlighter1_526_647_Open_Image.style.display='inline'; Codehighlighter1_526_647_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">   </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">   testGetWheels()   </span><span id="Codehighlighter1_526_647_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_526_647_Open_Text"><span style="COLOR: #000000">{   <br /></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />          assertEquals(expectedWheels,   myCar.getWheels());   </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">一个简单的测试方法：判断expectedWheels的值与myCar对象取得大值是否相等</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #008080">19</span><span style="COLOR: #008000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /></span><span style="COLOR: #000000">      }</span></span><span style="COLOR: #000000">   <br /></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img id="Codehighlighter1_690_707_Open_Image" onclick="this.style.display='none'; Codehighlighter1_690_707_Open_Text.style.display='none'; Codehighlighter1_690_707_Closed_Image.style.display='inline'; Codehighlighter1_690_707_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_690_707_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_690_707_Closed_Text.style.display='none'; Codehighlighter1_690_707_Open_Image.style.display='inline'; Codehighlighter1_690_707_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />      </span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">   </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">   tearDown()   </span><span id="Codehighlighter1_690_707_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_690_707_Open_Text"><span style="COLOR: #000000">{</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">todo   </span><span style="COLOR: #008000"><br /></span><span style="COLOR: #008080">21</span><span style="COLOR: #008000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /></span><span style="COLOR: #000000">      }</span></span><span style="COLOR: #000000">   <br /></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    <br /></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />  }</span></span></div><p><br />3 运行结果:<br />junit.framework.AssertionFailedError: expected:&lt;6&gt; but was:&lt;3&gt;<br /> at junit.framework.Assert.fail(Assert.java:47)<br /> at junit.framework.Assert.failNotEquals(Assert.java:282)<br /> at junit.framework.Assert.assertEquals(Assert.java:64)<br /> at junit.framework.Assert.assertEquals(Assert.java:201)<br /> at junit.framework.Assert.assertEquals(Assert.java:207)<br /> at TestCar.testGetWheels(TestCar.java:18)<br /> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<br /> at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)<br /> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)<br /> at java.lang.reflect.Method.invoke(Unknown Source)<br /> at junit.framework.TestCase.runTest(TestCase.java:154)<br /> at junit.framework.TestCase.runBare(TestCase.java:127)<br /> at junit.framework.TestResult$1.protect(TestResult.java:106)<br /> at junit.framework.TestResult.runProtected(TestResult.java:124)<br /> at junit.framework.TestResult.run(TestResult.java:109)<br /> at junit.framework.TestCase.run(TestCase.java:118)<br /> at junit.framework.TestSuite.runTest(TestSuite.java:208)<br /> at junit.framework.TestSuite.run(TestSuite.java:203)<br /> at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)<br /> at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)<br /> at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)</p><p>如果把Car.java中的返回值改为6,运行结果会成功.<br /></p><img src ="http://www.blogjava.net/matthew2006/aggbug/85185.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-12-03 14:49 <a href="http://www.blogjava.net/matthew2006/archive/2006/12/03/85185.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JUnit和单元测试入门简介(2)--转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/26/83617.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sun, 26 Nov 2006 07:16:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/26/83617.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/83617.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/26/83617.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/83617.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/83617.html</trackback:ping><description><![CDATA[3.6、JUnit一个实例 <p></p><p>在控制台中简单的范例如下： <br />1、写个待测试的Triangle类，创建一个TestCase的子类ExampleTest: <br />2、 ExampleTest中写一个或多个测试方法，断言期望的结果(注意：以test作为待测试的方法的开头，这样这些方法可以被自动找到并被测试) <br />3、 ExampleTest中写一个suite()方法，它会使用反射动态的创建一个包含所有的testXxxx方法的测试套件： <br />4、 ExampleTest可以写setUp()、tearDown()方法，以便于在测试时初始化或销毁测试所需的所有变量和实例。（不是必须的） </p><p>5、写一个main()方法以文本运行器或其它GUI的方式方便的运行测试 </p><p>6、编译ExampleTest，执行测试。 </p><p>3.7、Eclipse中JUnit的使用 </p><p>Eclipse自带了一个JUnit的插件，不用安装就可以在你的项目中开始测试相关的类，并且可以调试你的测试用例和被测试类。 </p><p>使用步骤如下： </p><p>1、新建一个测试用例，点击“File-&gt;New-&gt;Other…菜单项，在弹出的“New”对话框中选择”Java-&gt;JUnit”,下的TestCase 或TestSuite，就进入“New JUnit TestCase”对话框 </p><p>2、在“New JUnit TestCase”对话框填写相应的栏目，主要有Name（测试用例名），SuperClass（测试的超类一般是默认的junit.framework.TestCase），Class Under Test（被测试的类），Source Folder（测试用例保存的目录），Package（测试用例包名），及是否自动生成main,setUp,tearDown方法。 </p><p>3、如果点击下面的”Next&gt;”按钮，你还可以直接勾选你想测试的被测试类的方法，Eclipse将自动生成与被选方法相应的测试方法，点击“Fishish”按钮后一个测试用例就创建好了。 </p><p>4、编写完成你的测试用例后，点击“Run”按钮就可以看到运行结果了。 </p><p>3.8、JUnit的扩展应用 </p><p>以下罗列了些JUnit的扩展应用： </p><p>JUnit + HttpUnit=WEB功能测试工具 <br />JUnit + hansel =代码覆盖测试工具 <br />JUnit + abbot =界面自动回放测试工具 <br />JUnit + dbunit =数据库测试工具 <br />JUnit + junitperf=性能测试工具 </p><p>3.9、一些使用JUnit经验 </p><p>不要用TestCase的构造函数初始化，而要用setUp()和tearDown()方法。 <br />不要依赖或假定测试运行的顺序，因为JUnit利用Vector保存测试方法。所以不同的平台会按不同的顺序从Vector中取出测试方法。 <br />避免编写有副作用的TestCase。例如：如果随后的测试依赖于某些特定的交易数据，就不要提交交易数据。简单的回滚就可以了。 <br />当继承一个测试类时，记得调用父类的setUp()和tearDown()方法。 <br />将测试代码和工作代码放在一起，一边同步编译和更新。 <br />测试类和测试方法应该有一致的命名方案。如在工作类名前加上test从而形成测试类名。 <br />确保测试与时间无关，不要依赖使用过期的数据进行测试。导致在随后的维护过程中很难重现测试。 <br />如果你编写的软件面向国际市场，编写测试时要考虑国际化的因素。不要仅用母语的Locale进行测试。 <br />尽可能地利用JUnit提供地assert/fail方法以及异常处理的方法，可以使代码更为简洁。 <br />测试要尽可能地小，执行速度快。 </p><p><br />参考资料与附件 </p><p>1. http:// <a href="http://www.junit.org/">www.junit.org</a> JUnit官方网站 </p><p>2. <a href="http://bbs.51cmm.com/">http://bbs.51cmm.com</a> 的测试论坛 </p><p>3. <a href="http://www.uml.org.cn/">http://www.uml.org.cn</a> 的软件测试专栏 </p><p>4. 单元测试 《程序员》 2002年7期 </p><p>5. JUnit设计模式分析 《程序员》2003年6期 </p><p>6. 《软件测试和JUnit实践》 </p><p>7. 附件Triangle.java 一个要测试的类 </p><p></p><p><br />Triangle.java </p><p>/** </p><p>* this is Triangle class </p><p>* @author liujun </p><p>*/ </p><p>public class Triangle </p><p>{ </p><p>//定义三角形的三边 </p><p>protected long lborderA = 0; </p><p>protected long lborderB = 0; </p><p>protected long lborderC = 0; </p><p> </p><p>//构造函数 </p><p>public Triangle(long lborderA,long lborderB,long lborderC) </p><p>{ </p><p>this.lborderA = lborderA; </p><p>this.lborderB = lborderB; </p><p>this.lborderC = lborderC; </p><p>} </p><p>/** </p><p>* 判断是否是三角形 </p><p>* 是返回ture；不是返回false </p><p>*/ </p><p>public boolean isTriangle(Triangle triangle) </p><p>{ </p><p>boolean isTrue = false; </p><p>//判断边界，大于0小于200，出界返回false </p><p>if((triangle.lborderA&gt;0&amp;&amp;triangle.lborderA&lt;200) </p><p>&amp;&amp;(triangle.lborderB&gt;0&amp;&amp;triangle.lborderB&lt;200) </p><p>&amp;&amp;(triangle.lborderC&gt;0&amp;&amp;triangle.lborderC&lt;200)) </p><p>{ </p><p>//判断两边之和大于第三边 </p><p>if((triangle.lborderA&lt;(triangle.lborderB+triangle.lborderC)) </p><p>&amp;&amp;(triangle.lborderB&lt;(triangle.lborderA+triangle.lborderC)) </p><p>&amp;&amp;(triangle.lborderC&lt;(triangle.lborderA+triangle.lborderB))) </p><p>isTrue = true; </p><p>} </p><p>return isTrue; </p><p>} </p><p> </p><p>/** </p><p>* 判断三角形类型 </p><p>* 等腰三角形返回字符串“等腰三角形”； </p><p>* 等边三角形返回字符串“等边三角形”； </p><p>* 其它三角形返回字符串“不等边三角形”； </p><p>*/ </p><p>public String isType(Triangle triangle) </p><p>{ </p><p>String strType = ""; </p><p>// 判断是否是三角形 </p><p>if(this.isTriangle(triangle)) </p><p>{ </p><p>//判断是否是等边三角形 if(triangle.lborderA==triangle.lborderB&amp;&amp;triangle.lborderB==triangle.lborderC) </p><p>strType = "等边三角形"; </p><p>//判断是否是不等边三角形 </p><p>else if((triangle.lborderA!=triangle.lborderB)&amp;&amp; </p><p>(triangle.lborderB!=triangle.lborderC)&amp;&amp; </p><p>(triangle.lborderA!=triangle.lborderC)) </p><p>strType = "不等边三角形"; </p><p>else </p><p>strType="等腰三角形"; </p><p>} </p><p>return strType; </p><p>} </p><p>} </p><p>8. 附件ExampleTest.java 一个测试用例类 </p><p></p><p>ExampleTest.java </p><p>import junit.framework.*; </p><p>/** </p><p>* Some tests. </p><p>* </p><p>*/ </p><p>public class ExampleTest extends TestCase { </p><p>public Triangle triangle; </p><p>//初始化 </p><p>protected void setUp() { </p><p>triangle=new Triangle(10,2,9); </p><p>} </p><p> </p><p>public static Test suite() { </p><p>return new TestSuite(ExampleTest.class); </p><p>} </p><p>//函数isTriangle()的测试用例 </p><p>public void testIsTriangle() { </p><p>assertTrue(triangle.isTriangle(triangle)); </p><p>} </p><p>//函数isType()的测试用例 </p><p>public void testIsType() </p><p>{ </p><p>assertEquals("这次测试",triangle.isType(triangle),"不等边三角形"); </p><p>} </p><p> </p><p>//执行测试 </p><p>public static void main (String[] args) { </p><p>//文本方式 </p><p>junit.textui.TestRunner.run(suite()); </p><p>//Swingui方式 </p><p>//junit.swingui.TestRunner.run(suite().getClass()); </p><p>//awtui方式 </p><p>//junit.awtui.TestRunner.run(suite().getClass()); </p><p> </p><p>} </p><p>} <br /><br /></p><img src ="http://www.blogjava.net/matthew2006/aggbug/83617.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-26 15:16 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/26/83617.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JUnit和单元测试入门简介(1)--转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/26/83616.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sun, 26 Nov 2006 07:14:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/26/83616.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/83616.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/26/83616.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/83616.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/83616.html</trackback:ping><description><![CDATA[
		<p>1、几个相关的概念 </p>
		<p>白盒测试——把测试对象看作一个打开的盒子，程序内部的逻辑结构和其他信息对测试人员是公开的。 </p>
		<p>回归测试——软件或环境的修复或更正后的“再测试”，自动测试工具对这类测试尤其有用。 </p>
		<p>单元测试——是最小粒度的测试，以测试某个功能或代码块。一般由程序员来做，因为它需要知道内部程序设计和编码的细节。 </p>
		<p>JUnit ——是一个开发源代码的Java测试框架，用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例（用于java语言）。主要用于白盒测试，回归测试。 </p>
		<p>2、单元测试概述 </p>
		<p>2.1、单元测试的好处 </p>
		<p>A、提高开发速度——测试是以自动化方式执行的，提升了测试代码的执行效率。 </p>
		<p>B、提高软件代码质量——它使用小版本发布至集成，便于实现人员除错。同时引入重构概念，让代码更干净和富有弹性。 </p>
		<p>C、提升系统的可信赖度——它是回归测试的一种。支持修复或更正后的“再测试”，可确保代码的正确性。 </p>
		<p>2．2、单元测试的针对对象 </p>
		<p>A、面向过程的软件开发针对过程。 </p>
		<p>B、面向对象的软件开发针对对象。 </p>
		<p>C、可以做类测试，功能测试，接口测试（最常用于测试类中的方法）。 </p>
		<p>2.3、单元测试工具和框架 </p>
		<p>目前的最流行的单元测试工具是xUnit系列框架，常用的根据语言不同分为JUnit（java），CppUnit（C++），DUnit （Delphi ），NUnit（.net），PhpUnit（Php ）等等。该测试框架的第一个和最杰出的应用就是由Erich Gamma （《设计模式》的作者）和Kent Beck（XP（Extreme Programming）的创始人 ）提供的开放源代码的JUnit。<br />3.Junit入门简介 </p>
		<p>
		</p>
		<p>3.1、JUnit的好处和JUnit单元测试编写原则 </p>
		<p>好处： </p>
		<p>A、可以使测试代码与产品代码分开。 </p>
		<p>B、针对某一个类的测试代码通过较少的改动便可以应用于另一个类的测试。 </p>
		<p>C、易于集成到测试人员的构建过程中，JUnit和Ant的结合可以实施增量开发。 </p>
		<p>D、JUnit是公开源代码的，可以进行二次开发。 </p>
		<p>C、可以方便地对JUnit进行扩展。 </p>
		<p>编写原则： </p>
		<p>A、是简化测试的编写，这种简化包括测试框架的学习和实际测试单元的编写。 </p>
		<p>B、是使测试单元保持持久性。 </p>
		<p>C、是可以利用既有的测试来编写相关的测试。 </p>
		<p>3.2、JUnit的特征 </p>
		<p>A、使用断言方法判断期望值和实际值差异，返回Boolean值。 </p>
		<p>B、测试驱动设备使用共同的初始化变量或者实例。 </p>
		<p>C、测试包结构便于组织和集成运行。 </p>
		<p>D、支持图型交互模式和文本交互模式。 </p>
		<p>3.3、JUnit框架组成 </p>
		<p>A、对测试目标进行测试的方法与过程集合，可称为测试用例(TestCase)。 </p>
		<p>B、测试用例的集合，可容纳多个测试用例(TestCase)，将其称作测试包(TestSuite)。 </p>
		<p>C、测试结果的描述与记录。(TestResult) 。 </p>
		<p>D、测试过程中的事件监听者(TestListener)。 </p>
		<p>E、每一个测试方法所发生的与预期不一致状况的描述，称其测试失败元素(TestFailure) </p>
		<p>F、JUnit Framework中的出错异常（AssertionFailedError）。 </p>
		<p>JUnit框架是一个典型的Composite模式：TestSuite可以容纳任何派生自Test的对象；当调用TestSuite对象的run()方法是，会遍历自己容纳的对象，逐个调用它们的run()方法。（可参考《程序员》2003-6期）。 <br />3.4、JUnit的安装和配置 </p>
		<p>
		</p>
		<p>JUnit安装步骤分解： </p>
		<p>在<a href="http://download.sourceforge.net/junit/">http://download.sourceforge.net/junit/</a>中下载JUnit包并将Junit压缩包解压到一个物理目录中（例如C：＼Junit3.8.1）。 <br />记录Junit.jar文件所在目录名（例如C：＼Junit3.8.1\Junit.jar）。 <br />进入操作系统（以Windows2000操作系统为准），按照次序点击“开始　设置　控制面板”。 <br />在控制面板选项中选择“系统”，点击“环境变量”，在“系统变量”的“变量”列表框中选择“CLASS-PATH”关键字（不区分大小写），如果该关键字不存在则添加。 <br />双击“CLASS-PATH”关键字添加字符串“C:＼Junit3.8.1\Junti.jar”(注意，如果已有别的字符串请在该字符串的字符结尾加上分号“；”)，这样确定修改后Junit就可以在集成环境中应用了。 <br />对于IDE环境，对于需要用到的JUnit的项目增加到lib中，其设置不同的IDE有不同的设置 。 <br />3.5、JUnit中常用的接口和类 </p>
		<p>Test接口——运行测试和收集测试结果 </p>
		<p>Test接口使用了Composite设计模式，是单独测试用例 （TestCase），聚合测试模式（TestSuite）及测试扩展（TestDecorator）的共同接口。 <br />它的public int countTestCases（）方法，它来统计这次测试有多少个TestCase，另外一个方法就是public void　run（ TestResult ），TestResult是实例接受测试结果， run方法执行本次测试。 <br />TestCase抽象类——定义测试中固定方法 </p>
		<p>TestCase是Test接口的抽象实现，（不能被实例化，只能被继承）其构造函数TestCase(string name)根据输入的测试名称name创建一个测试实例。由于每一个TestCase在创建时都要有一个名称，若某测试失败了，便可识别出是哪个测试失败。 <br />TestCase类中包含的setUp()、tearDown()方法。setUp()方法集中初始化测试所需的所有变量和实例，并且在依次调用测试类中的每个测试方法之前再次执行setUp()方法。tearDown()方法则是在每个测试方法之后，释放测试程序方法中引用的变量和实例。 <br />开发人员编写测试用例时，只需继承TestCase，来完成run方法即可，然后JUnit获得测试用例，执行它的run方法，把测试结果记录在TestResult之中。 <br />Assert静态类——一系列断言方法的集合 </p>
		<p>Assert包含了一组静态的测试方法，用于期望值和实际值比对是否正确，即测试失败，Assert类就会抛出一个AssertionFailedError异常，JUnit测试框架将这种错误归入Failes并加以记录，同时标志为未通过测试。如果该类方法中指定一个String类型的传参则该参数将被做为AssertionFailedError异常的标识信息，告诉测试人员改异常的详细信息。 <br />JUnit 提供了6大类31组断言方法，包括基础断言、数字断言、字符断言、布尔断言、对象断言。 <br />其中assertEquals（Object expcted,Object actual)内部逻辑判断使用equals()方法，这表明断言两个实例的内部哈希值是否相等时，最好使用该方法对相应类实例的值进行比较。而assertSame（Object expected,Object actual）内部逻辑判断使用了Java运算符“==”，这表明该断言判断两个实例是否来自于同一个引用（Reference），最好使用该方法对不同类的实例的值进行比对。asserEquals(String message,String expected,String actual)该方法对两个字符串进行逻辑比对，如果不匹配则显示着两个字符串有差异的地方。ComparisonFailure类提供两个字符串的比对，不匹配则给出详细的差异字符。 <br />TestSuite测试包类——多个测试的组合 </p>
		<p>TestSuite类负责组装多个Test Cases。待测得类中可能包括了对被测类的多个测试，而TestSuit负责收集这些测试，使我们可以在一个测试中，完成全部的对被测类的多个测试。 <br />TestSuite类实现了Test接口，且可以包含其它的TestSuites。它可以处理加入Test时的所有抛出的异常。 <br />TestSuite处理测试用例有6个规约（否则会被拒绝执行测试） <br />A 测试用例必须是公有类（Public） </p>
		<p>B 测试用例必须继承与TestCase类 </p>
		<p>C 测试用例的测试方法必须是公有的（ Public ） </p>
		<p>D 测试用例的测试方法必须被声明为Void </p>
		<p>E 测试用例中测试方法的前置名词必须是test </p>
		<p>F 测试用例中测试方法误任何传递参数 </p>
		<p>n TestResult结果类和其它类与接口 </p>
		<p>TestResult结果类集合了任意测试累加结果，通过TestResult实例传递个每个测试的Run（）方法。TestResult在执行TestCase是如果失败会异常抛出 <br />TestListener接口是个事件监听规约，可供TestRunner类使用。它通知listener的对象相关事件，方法包括测试开始startTest(Test test)，测试结束endTest(Test test),错误，增加异常addError(Test test,Throwable t)和增加失败addFailure(Test test,AssertionFailedError t) <br />TestFailure失败类是个“失败”状况的收集类，解释每次测试执行过程中出现的异常情况。其toString()方法返回“失败”状况的简要描述 </p>
		<p>
				<br />
		</p>
<img src ="http://www.blogjava.net/matthew2006/aggbug/83616.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-26 15:14 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/26/83616.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在开发过程中怎样利用单元和功能测试--转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/26/83614.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sun, 26 Nov 2006 07:03:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/26/83614.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/83614.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/26/83614.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/83614.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/83614.html</trackback:ping><description><![CDATA[
		<p>在过去的几年中，单元测试逐渐成为我编写软件的核心内容，在这里要感谢一种叫做极端编程-XP（注1）(见“资源”一节)的简便程序设计方法。这种方法要求我为新加入的每个函数都编写单元测试，并且维护这些测试。没有通过单元测试，我就不能将任何一个的代码加到模块中。在代码基数增长的同时，这些测试允许开发者有依据地将改变集成起来。起初，我认为这些单元测试就足以应付全局，没有必要涉及到功能测试。噢，又错了。功能测试和单元测试完全不同的两者。我花费了很长的时间才理解到两者的区别，以及如何将它们结合起来，用以改进开发进程。</p>
		<br />
		<p>本文探讨了单元测试和功能测试之间的差别，同时介绍在你的日常开发的过程中如何来利用它测试和开发过程作为一个开发人员，测试如此之重要，以至于你甚至应该花费几乎所有的时间来完成它。它不仅需要只被划分为开发过程中的某个特定阶段。显然，它不该是在你把系统交付给客户之前完成的最后一项任务。然而，你又如何得知它在何时结束呢？或是你如何得知是否因为修改一个微小的bug而破坏了系统的主要功能呢？或是系统可能会演化成超乎现在想象的模样？测试，单元的和功能的都应该是开发的过程中的一部分。</p>
		<br />
		<p>单元测试应成为你编写代码的核心环节，尤其当你在从事一个项目时，紧张的时间约束你的开发进度，你也很想让它是在可控的有序下进行。我希望测试也是在你编写代码之前编写测试时的重要内容。</p>
		<br />
		<p>一套适用的单元测试应具备以下功能：<br /><strong>说明可能的最佳适用设计<br />提供类文档的最佳格式<br />判断一个类何时完成<br />增强开发人员对代码的信心<br />是快速重构的基础</strong></p>
		<br />
		<p>在系统中自然要包含单元测试所需的设计文档。重新阅读它，你会发现这是软件开发进程中的圣杯，文档跟随系统的变化而逐步演化。为每一个类提供完备的文档比起为它提供一系列的使用框架，或是一系列可控的输入要好得多。这样，设计文档就会因为单元测试的逐步通过而随时更新。</p>
		<br />
		<p>你应该在你编写代码之前完成编写测试的工序。这样做会为测试所涉及的类提供设计方案，并促使你关注代码中更小的程序模块。这种练习也会使设计方案变得更加简单。你不能试图去了解将来的情形，去实现不必要的功能。编写测试工作也会让你清楚类会在什么时间结束。可以说，当所有的测试通过时，任务也就完成了。</p>
		<br />
		<p>最后，单元测试会提供给你更高级别的依据，这绝对会满足开发者的。如果你在改动代码的同时，进行单元测试，你就会在你破坏的同时立即察觉到事态的发生。</p>
		<br />
		<p>功能测试甚至比单元测试更加重要，因为它们说明了你的系统就要预备发布了。功能测试将把你的工作系统放置于一个可用的状态中。</p>
		<br />
		<p>一套适用的功能测试应具备以下功能：<br /><strong>有效地掌握用户的需求<br />向项目组成员（包括用户和开发者）给出系统面临这些需求的依据</strong></p>
		<br />
		<p>功能测试要在有效地情况下掌握用户的需求。而传统的开发者是在使用的过程中发现需求的。通常，人们赞同使用项目工程并且花费相当的时间去重新定制它们。当它们被完成时，它们所得到的仅仅是一堆废纸。功能测试雷同于自行生效的使用项目的情况。极端程序设计方法（ExtremeProgramming）能够说明这种概念。XP 的说法就是对未来发生在用户和开发者之间的交流技巧的描述。功能测试也是这种交流的结果。而没有功能测试，这种说法也不会建立起来的。</p>
		<br />
		<p>功能测试恰好填充了在单元测试和向项目小组提交的代码依据之间的空隙。单元测试会漏过许多的bug。它可以给出代码中你所需的所有有效部分，它也会给你所需的整个系统。功能测试可以使单元测试里漏掉的问题曝光。一系列可维护的，自动化的功能测试也会有漏网的情况，但是它至少比独立地进行最全面的单元测试要有用得多。</p>
		<br />
		<p>
				<br />
				<strong>单元测试VS 功能测试<br /></strong>单元测试告诉开发者代码使事情正确地被执行，而功能测试所说的则是代码在正确地发挥功效。</p>
		<br />
		<p>
				<strong>
						<u>单元测试</u>
				</strong>
				<br />单元测试是从开发者的角度来编写的。它们确保类的每个特定方法成功执行一系列特定的任务。每一个测试都要保证对于给定的一个已知的输入应该得到所期望的输出。</p>
		<br />
		<p>编写一系列可维护、自动化、没有测试框架的单元测试几乎是不可能的。在你开始之前，选择一个项目小组都认可的框架。不断地应用它，逐渐地喜欢它。在极端编程的介绍网页上（见资源一节），有很多适用的单元测试框架。我喜欢用的是Juint 来进行Java 代码的测试。</p>
		<br />
		<p>
				<u>
						<strong>功能测试</strong>
				</u>
				<br />功能测试则是从用户的角度来编写的。这些测试保证系统能够按照用户所期望的那样去运行。很多时候，开发一个完整的系统更像是建造一座大楼。当然，这种比喻并不是完全地恰当，但我们可以扩展它，来理解单元测试和功能测试之间的区别。</p>
		<br />
		<p>单元测试类似于一个建筑检查员对房屋的建设现场进行检查。他注重的是房屋内部不同的系统，地基，架构设计，电气化，垂直的线条等等。他检查房屋的某个部分，以确保它在安全状态下，正确无误地工作，即是说，直接针对房屋的代码。功能测试在这个剧本里类似于房屋的主人在检查同样的建设场地。他所期望的是房屋的内部系统正常地运转，并且房屋检查员执行了他的任务。房屋的主人看重的是生活在这样的房屋中会是什么样子。他关注这间房屋的外貌，不同的房间有合适的空间，房屋适用于家庭的需要，窗户恰好位于最佳采光的位置。房屋的主人运行的是对房屋的功能测试，他站在用户的角度上。房屋检查员运行的是单元测试，他是站在建设者的角度上。</p>
		<br />
		<p>象单元测试一样，编写一系列可维护、自动化、没有测试框架的功能测试几乎是不可能的。Junit在单元测试方面做得很好；然而，它在试图编写功能测试时就显得比较松散。Junit 不等同于功能测试。现在已经有满足这个功能的产品问世了，但是我还没有看到它们被应用于开发产品过程里。如果你不能找到一个测试框架的话，就只好自己创建一个了。无论我们在建立一个项目时多么聪明，建立的系统多么灵活，如果我们的产品不能用，我们就是在浪费时间。结论是，功能测试是开发进程中最重要的一部分。</p>
		<br />
		<p>因为两种类型的测试都是必要的，你会需要编写它们的指南。</p>
		<br />
		<p>
				<strong>如何编写单元测试<br /></strong>在你开始编写单元测试很容易被激动的情绪感染。最简单的起步方式就是为新的代码创建单元测试。为已经存在的代码创建单元测试是一种比较有难度的开始方式，但是也是可行的。）从新的代码开始，习惯了这样的步骤后，还要坚持重新阅读现有代码，并为它们创建一套测试程序。</p>
		<br />
		<p>就像前面提到过的一样，你应该在你编写要测试的代码之前编写单元测试。如何做到为还不存在的事物编写测试呢？好问题！掌握这个能力需要90％的智力和10％技巧。我的意思是你只需假装是在为已有的类编写测试。接下来，进行编写的工作。最初，你将出现很多语法错误，但是let it be，不要理会它。紧接着进行单元测试，修改语法错误（即是说，只用你自己定义的测试接口来实现类），再一次进行测试。重复这个过程，每一次都写下充足的代码去修改错误，进行测试直到它们通过为止。当所有的单元测试都通过时，代码才算真正地完成了。</p>
		<br />
		<p>一般地说，你的类应具有开放的单元测试方式。然而，带有直截了当的功能性的方法比如说，Java 语言里的Getting 和Setting 读写方法，就不需要单元测试，除非它们是以“特殊”的方式进行的。接下来的指导就是，当你感到需要对代码中的某些特性添加注释时，同时要编写出单元测试。如果你同很多的程序员一样，厌恶为代码写注释，单元测试就是将你的代码的特性文档化的一种好方法。</p>
		<br />
		<p>将单元测试同被测试的相关的类打包在一起。（这种组织的方式允许每一个单元测试都能够直接访问类中被打包和保护的方法和参数）。要避免在单元测试中用到域对象（domain object）。域对象就是对于一个应用程序特定的对象。</p>
		<br />
		<p>例如，电子表格应用程序有个工作簿对象，它就是一个域对象。如果你的一个类已经知道了域对象，在你的测试中用到这些对象是很好的。但是如果你的类没有涉及到这些对象，就不要在测试里让它们同类纠缠不清了。不这样做的话，就会产生打包的代码被重用。经常是为一个项目创建的类也可以应用于其他的项目，这样可能会出现直接重用这些类的情况。但是如果针对这些类的测试也用于另外的项目对象，让测试生效会很费时，通常测试不是被抛弃掉就是被重新编写。</p>
		<br />
		<p>以上的一些技巧会让你从中受益，但最重要的是如果你不实际地去做，就永远不会对单元测试有全面、深入的理解。更早地运行测试，并且在整个过程中都在代码中给出全面的依据。当项目进展时，你会随时添加更多的特性。运行测试就会提醒你，实现刚添加的特性会不会破坏已有的东西。</p>
		<br />
		<p>在你已经掌握编写单元测试的技巧之后，你需要重新阅读已存在的代码。的确，为它们编写代码可能会是一场挑战。但是千万不要为了测试的目的而测试。可以说，编写测试是一件紧跟时效的事情，尤其是当你发现要修改一个没有好的测试程序的类时，那就是添加测试的恰当时机。和平常一样，单元测试应该具备类每个方法的特性。实现测试的一个最简单的方法就是，测试的同时一定要注意代码的注释。在单元测试中，不能放过任何一个注释，在描述测试方法的开始就要为单元测试添加大量的注释中。</p>
		<br />
		<p>
				<strong>如何编写功能测试<br /></strong>尽管功能测试是如此重要，它也有个开发过程里丑陋的继生子的坏名声。在大多数的项目里，是由一个独立的工作组来完成功能测试的工作。通常需要一群人在系统中的相互协助才能保证工序的正确运行。这种通常的看法和队伍的组建的做法，都是非常愚蠢的。</p>
		<br />
		<p>功能测试同单元测试相类似。一旦要编写有用户涉入的产品的代码（例如，对话框）时，就要编写测试，但是一定要在实际编写代码之前做。一旦你开始了一项新任务，就要在功能测试的框架里清楚地描述这个任务的内容。你加入的新代码的同时进行单元测试，开发工作就向前持续进行。</p>
		<br />
		<p>当所有的单元测试都进行通过后，再进行最初的功能测试来判断项目是否可以通过，或是需要修改。理想的状况下，功能测试小组的概念应该不存在的。开发者应该同用户一同编写功能测试。系统通过了一系列的单元测试后，负责进行功能测试的小组成员就要改变初试测试的参数，再进行系统的功能测试。</p>
		<br />
		<p>
				<strong>单元测试和功能测试之间的界线<br /></strong>一般情况下，很难划清在单元测试和功能测试之间的界限。说实话，一直以来，我就不知道这个界线应该定在哪里。当编写单元测试时，我用以下几个方法来判定单元测试是不是已经变成了功能测试：<br />如果单元测试超越了类之间的界限，它可能变成了功能测试<br />如果单元测试变得非常的复杂，它可能变成了功能测试<br />如果单元测试变得很脆弱（即是说，它已经成为一个测试，但是却因为要迎合不同用户需求的改变而被动地变化），它可能变成了功能测试<br />如果单元测试比需要测试的代码还要难于编写，它可能变成了功能测试</p>
		<br />
		<p>
				<br />注意“它可能变成了功能测试”的说法，在这里没有严格的标准。在单元测试和功能测试之间是有界线的，但是你必须自己判定它在哪里。单元测试进行地顺利，特定的测试逾越两者界线的过渡就越明显。</p>
		<br />
		<p>
				<strong>结论</strong>
				<br />单元测试以开发者的角度来编写，并注重被测试类的特性。当编写单元测试时，利用以下几条指导：<br /><strong>在类代码进行测试之前编写单元测试<br />在单元测试里掌握代码的注释<br />测试所有执行特定功能的公用程序（即是说，和Java 语言中的Getting 和Setting 读写方法不同的方法。除非它们是通过一种特殊的方式来完成Getting 和Setting 功能的。）<br />将所有的测试项目同被测试的类打包在一起，并且分配它们对在模块包内的和被保护成员<br />的访问权限<br />在单元测试中避免使用某些特定的对象</strong></p>
		<br />
		<p>功能测试也需要从用户的角度出发来编写，并且注重用户所感兴趣的系统功能。选择一个适当的功能测试框架，或是开发出一种，并利用这些功能测试来制定用户们想要的东西。通过这种方式，功能测试的人员可以获得一个自动的工具，并且对使用工具的习惯有了一个好的起点。</p>
		<br />
		<p>将单元测试和功能测试作为开发进程的核心内容。这样做，你就会确定系统在正常运转。如果没有，你恐怕不能保证系统是正常工作的。测试可能不是一件好玩的事情，但是从事单元测试和功能测试会使开发过程里含有更多的乐趣。</p>
		<br />
		<p>
				<strong>资源</strong>
				<br />“利用Ant 和JUnit 改进开发过程”（开发工作，2000 年12 月）揭示了单元测试的益处，尤其是应用了Ant 和Junit 之后。<br />开始了解极端编程的方法<br />从极端编程的网页上下载各种单元测试的框架</p>
<img src ="http://www.blogjava.net/matthew2006/aggbug/83614.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-26 15:03 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/26/83614.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件测试基础(3)--转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/26/83613.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sun, 26 Nov 2006 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/26/83613.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/83613.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/26/83613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/83613.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/83613.html</trackback:ping><description><![CDATA[
		<span style="FONT-SIZE: 12pt">
				<p align="left">3. 测试用例开发</p>
				<p align="left">一个好的测试用例就是有一个合理的概率来找到Bug，不要冗余，要有针对性，一个测试只针对一件事情。特别是功能测试的时候，如果一个测试是测了两项功能，那么如果测试结果失败的话，就不知道到底是哪项功能出了问题。</p>
				<p align="left">测试用例开发中主要使用的技术有等价类划分，边界值的分析，Error Guessing Testing。</p>
				<p align="left">等价类划分是根据输入输出条件，以及自身的一些特性分成两个或更多个子集，来减少所需要测试的用例个数，并且能用很少的测试用例来覆盖很多的情况，减少测试用例的冗余度。在等价类划分中，最基本的划分是一个为合法的类，一个为不合法的类。</p>
				<p align="left">边界值的分析是利用了一个规律，即程序最容易发生错误的地方就是在边界值的附近，它取决于变量的类型，以及变量的取值范围。一般对于有n个变量时，会有6n 1个测试用例，取值分别是min-1, min, min 1, normal, max-1, max,max 1的组合。边界值的分析的缺点，是对逻辑变量和布尔型变量不起作用，还有可能会忽略掉某些输入的组合。</p>
				<p align="left">Error Guessing Testing完全靠的是经验，所设计的测试用例就是常说的猜测。感觉到软件在某个地方可能出错，就去设计相应的测试用例，这主要是靠实际工作中所积累的经验和知识。其优点是速度快，只要想得到，就能很快设计出测试用例。缺点就是没有系统性，无法知道覆盖率会有多少，很可能会遗漏一些测试领域。</p>
				<p align="left">实际上在微软是采用一些专门的软件或工具负责测试用例的管理，有一些测试信息可以被记录下来，比如测试用例的简单描述，在哪些平台执行，是手工测试还是自动测试，运行的频率是每天运行一次，还是每周运行一次。此外还有清晰的测试通过或失败的标准，以及详细记录测试的每个步骤。</p>
				<p align="left">4. Bug跟踪过程</p>
				<p align="left">在软件开发项目中，测试人员的一项最重要使命就是对所有已知Bug进行有效的跟踪和管理，保证产品中出现的所有问题都可以得到有效的解决。一般地，项目组发现、定位、处理和最终解决一个Bug的过程包括Bug报告、Bug评估和分配、Bug处理、Bug关闭等四个阶段：</p>
				<p align="left">1）测试工程师在测试过程中发现新的Bug后，应向项目组报告该Bug的位置、表现、当前状态等信息。项目组在Bug数据库中添加该Bug的记录。</p>
				<p align="left">2）开发经理对已发现的Bug进行集中讨论，根据Bug对软件产品的影响来评估Bug的优先级，制定Bug的修正策略。按照Bug的优先级顺序和开发人员的工作安排，开发经理将所有需要立即处理的Bug分配给相应的开发工程师。</p>
				<p align="left">3）开发工程师根据安排对特定的Bug进行处理，找出代码中的错误原因，修改代码，重新生成产品版本。</p>
				<p align="left">4）开发工程师处理了Bug之后，测试人员需要对处理后的结果进行验证，经过验证确认已正确处理的Bug被标记为关闭（Close）状态。测试工程师既需要验证Bug是否已经被修正，也需要确定开发人员有没有在修改代码的同时引入新的Bug。</p>
				<p align="left">5. Bug的不同处理方式</p>
				<p align="left">在某些情况下，Bug已处理并不意味着Bug已经被修正。开发工程师可以推迟Bug的修正时间，也可以在分析之后告知测试工程师这实际上不是一个真正的Bug。也就是说，某特定的Bug经开发工程师处理之后，该Bug可能包括以下几种状态。</p>
				<p align="left">已修正：开发工程师已经修正了相应的程序代码，该Bug不会出现了。</p>
				<p align="left">可推迟：该Bug的重要程度较低，不会影响当前应提交版本的主要功能，可安排在下一版本中再行处理。</p>
				<p align="left">设计问题：该Bug与程序实现无关，其所表现出来的行为完全符合设计要求，对此应提交给程序经理处理。</p>
				<p align="left">无需修正：该Bug的重要程度非常低，根本不会影响程序的功能，项目组没有必要在这些Bug上浪费时间。</p>
				<p align="left">
				</p>
				<p align="left">五、成为优秀测试工程师的要求</p>
				<p align="left">要成为一名优秀的测试工程师，首先对计算机的基本知识要有很好的了解，精通一门或多门的编程语言，具备一定的程序调试技能，掌握测试工具的开发和使用技术。同时要比较细心，会按照任务的轻重缓急来安排自己的工作，要有很好的沟通能力。此外，还要善于用非常规的方式思考问题，尽可能多的参加软件测试项目，在实践中学习技能，积累经验，不断分析和总结软件开发过程中可能出错的环节。这样，一名优秀的测试工程师就从软件测试的实践中脱颖而出了。</p>
		</span>
<img src ="http://www.blogjava.net/matthew2006/aggbug/83613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-26 14:55 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/26/83613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件测试基础(2)--转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/26/83612.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sun, 26 Nov 2006 06:53:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/26/83612.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/83612.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/26/83612.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/83612.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/83612.html</trackback:ping><description><![CDATA[
		<p>
				<b>4. </b>
				<b>基于模型的测试</b>
		</p>
		<p>模型实际上就是用语言把一个系统的行为描述出来，定义出它可能的各种状态，以及它们之间的转换关系，即状态转换图。模型是系统的抽象。基于模型的测试是利用模型来生成相应的测试用例，然后根据实际结果和原先预想的结果的差异来测试系统，过程如下图所示。</p>
		<p>
				<b>三、软件测试的类型</b>
		</p>
		<p>常见的软件测试类型有：</p>
		<p>BVT (Build Verification Test)</p>
		<p>BVT是在所有开发工程师都已经检入自己的代码，项目组编译生成当天的版本之后进行，主要目的是验证最新生成的软件版本在功能上是否完整，主要的软件特性是否正确。如无大的问题，就可以进行相应的功能测试。BVT优点是时间短，验证了软件的基本功能。缺点是该种测试的覆盖率很低。因为运行时间短，不可能把所有的情况都测试到。</p>
		<p>Scenario Tests（基于用户实际应用场景的测试）</p>
		<p>在做BVT、功能测试的时候，可能测试主要集中在某个模块，或比较分离的功能上。当用户来使用这个应用程序的时候，各个模块是作为一个整体来使用的，那么在做测试的时候，就需要模仿用户这样一个真实的使用环境，即用户会有哪些用法，会用这个应用程序做哪些事情，操作会是一个怎样的流程。加了这些测试用例后，再与BVT、功能测试配合，就能使软件整体都能符合用户使用的要求。Scenario Tests优点是关注了用户的需求，缺点是有时候难以真正模仿用户真实的使用情况。</p>
		<p>Smoke Test</p>
		<p>在测试中发现问题，找到了一个Bug，然后开发人员会来修复这个Bug。这时想知道这次修复是否真的解决了程序的Bug，或者是否会对其它模块造成影响，就需要针对此问题进行专门测试，这个过程就被称为Smoke Test。在很多情况下，做Smoke Test是开发人员在试图解决一个问题的时候，造成了其它功能模块一系列的连锁反应，原因可能是只集中考虑了一开始的那个问题，而忽略其它的问题，这就可能引起了新的Bug。Smoke Test优点是节省测试时间，防止build失败。缺点是覆盖率还是比较低。</p>
		<p>此外，Application Compatibility Test（兼容性测试），主要目的是为了兼容第三方软件，确保第三方软件能正常运行，用户不受影响。Accessibility Test（软件适用性测试），是确保软件对于某些有残疾的人士也能正常的使用，但优先级比较低。其它的测试还有Functional Test（功能测试）、Security Test（安全性测试）、Stress Test（压力测试）、Performance Test（性能测试）、Regression Test（回归测试）、Setup/Upgrade Test（安装升级测试）等。</p>
		<p>
		</p>
		<p>
				<b>四、微软的软件测试工作</b>
		</p>
		<p>
				<b>1. </b>
				<b>基本情况</b>
		</p>
		<p>测试在微软公司是一项非常重要的工作，微软公司在此方面的投入是非常巨大的。微软对测试的重视表现在工程开发队伍的人员构成上，微软的项目经理、软件开发人员和测试人员的比例基本是1：3：3或1：4：4，可以看出开发人员与测试人员的比例是1：1。对于测试的重视还表现在最后产品要发布的时候，此产品的所有相关部门都必须签字，而测试人员则具有绝对的否决权。</p>
		<p>测试人员中分成两种职位，Software Development Engineer in Test（测试组的软件开发工程师）实际上还是属于开发人员，他们具备编写代码的能力和开发工具软件的经验，侧重于开发自动化测试工具和测试脚本，实现测试的自动化。Software Test Engineer（软件测试工程师）具体负责测试软件产品，主要完成一些手工测试以及安装配置测试。</p>
		<p>
				<b>2. </b>
				<b>测试计划</b>
		</p>
		<p>测试计划是测试人员管理测试项目，在软件中寻找Bug的一种有效的工具。测试计划主要有两个作用，一是评判团队的测试覆盖率以及效率，让测试工作很有条理的逐步展开。二是有利于与项目经理、开发人员进行沟通。有了测试计划之后，他们就能够知道你是如何开展测试工作的，他们也会从中提出很多有益的意见，确保测试工作顺利进行。总之，有了测试计划可以更好的完成测试工作，确保用户的满意度。</p>
		<p>测试人员在编写测试计划之前，应获得以下文档：</p>
		<p>1）程序经理编写的产品功能说明书或产品开发计划；</p>
		<p>2）程序经理或开发人员提供的开发进度表。</p>
		<p>根据产品的特性及开发进度安排，测试人员制定具体的测试计划。测试计划通常包括以下内容：</p>
		<p>1）测试目标和发布条件：</p>
		<p>a. 给出清晰的测试目标描述；</p>
		<p>b. 定义产品的发布条件，即在达到何种测试目标的前提下才可以发布产品的某个特定版本。</p>
		<p>2）待测产品范围：</p>
		<p>a. 软件主要特性/功能说明，即待测软件主要特性的列表；</p>
		<p>b. 特性/功能测试一览，应涵盖所有特性、对话框、菜单和错误信息等待测内容，并列举每个测试范围内要重点考虑的关键功能。</p>
		<p>3）测试方法描述：</p>
		<p>a. 定义测试软件产品时使用的测试方法；</p>
		<p>b. 描述每一种特定的测试方法可以覆盖哪些测试范围。</p>
		<p>4）测试进度表：</p>
		<p>a. 定义测试里程碑；</p>
		<p>b. 定义当前里程碑的详细测试进度。</p>
		<p>5）测试资源和相关的程序经理/开发工程师：</p>
		<p>a. 定义参与测试的人员；</p>
		<p>b. 描述每位测试人员的职责范围；</p>
		<p>c. 给出与测试有关的程序经理/开发工程师的相关信息。</p>
		<p>6）配置范围和测试工具：</p>
		<p>a. 给出测试时使用的所有计算机平台列表；</p>
		<p>b. 描述测试覆盖了哪些硬件设备；</p>
		<p>c. 测试时使用的主要测试工具。</p>
		<p>此外，还应列出测试中可能会面临的风险及测试的依赖性，即测试是否依赖于某个产品或某个团队。比如此项测试依赖性WindowsCE这个操作系统，而这个系统要明年2月份才能做好，那么此项测试就可能只有在明年5月份才能完成，这样就存在着依赖关系。如果那个团队的开发计划往后推，则此项测试也会被推迟。<br /></p>
<img src ="http://www.blogjava.net/matthew2006/aggbug/83612.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-26 14:53 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/26/83612.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件测试基础(1)--转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/26/83610.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sun, 26 Nov 2006 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/26/83610.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/83610.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/26/83610.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/83610.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/83610.html</trackback:ping><description><![CDATA[
		<p>
				<b>一、软件测试概述</b>
		</p>
		<br />
		<p>软件测试是软件开发过程的重要组成部分，是用来确认一个程序的品质或性能是否符合开发之前所提出的一些要求。软件测试的目的，第一是确认软件的质量，其一方面是确认软件做了你所期望的事情（Do the right thing），另一方面是确认软件以正确的方式来做了这个事件（Do it right）。第二是提供信息，比如提供给开发人员或程序经理的反馈信息，为风险评估所准备的信息。第三软件测试不仅是在测试软件产品的本身，而且还包括软件开发的过程。如果一个软件产品开发完成之后发现了很多问题，这说明此软件开发过程很可能是有缺陷的。因此软件测试的第三个目的是保证整个软件开发过程是高质量的。</p>
		<p>软件质量是由几个方面来衡量的：一、在正确的时间用正确的的方法把一个工作做正确（Doing the right things right at the right time.）。二、符合一些应用标准的要求，比如不同国家的用户不同的操作习惯和要求，项目工程中的可维护性、可测试性等要求。三、质量本身就是软件达到了最开始所设定的要求，而代码的优美或精巧的技巧并不代表软件的高质量（Quality is defined as conformance to requirements, not as “goodness” or “elegance”.）。四、质量也代表着它符合客户的需要（Quality also means “meet customer needs”.）。作为软件测试这个行业，最重要的一件事就是从客户的需求出发，从客户的角度去看产品，客户会怎么去使用这个产品，使用过程中会遇到什么样的问题。只有这些问题都解决了，软件产品的质量才可以说是上去了。</p>
		<p>测试人员在软件开发过程中的任务：</p>
		<p>1、寻找Bug；</p>
		<p>2、避免软件开发过程中的缺陷；</p>
		<p>3、衡量软件的品质；</p>
		<p>4、关注用户的需求。</p>
		<p>总的目标是：确保软件的质量。</p>
		<p>
				<b>二、常用的软件测试方法</b>
		</p>
		<p>
				<b>1. </b>
				<b>黑盒测试</b>
		</p>
		<p>黑盒测试顾名思义就是将被测系统看成一个黑盒，从外界取得输入，然后再输出。整个测试基于需求文档，看是否能满足需求文档中的所有要求。黑盒测试要求测试者在测试时不能使用与被测系统内部结构相关的知识或经验，它适用于对系统的功能进行测试。</p>
		<p>黑盒测试的优点有：<br />1）比较简单，不需要了解程序内部的代码及实现；</p>
		<p>2）与软件的内部实现无关；</p>
		<p>3）从用户角度出发，能很容易的知道用户会用到哪些功能，会遇到哪些问题；</p>
		<p>4）基于软件开发文档，所以也能知道软件实现了文档中的哪些功能；</p>
		<p>5）在做软件自动化测试时较为方便。</p>
		<br />
		<p>黑盒测试的缺点有：<br />1）不可能覆盖所有的代码，覆盖率较低，大概只能达到总代码量的30%；</p>
		<p>2）自动化测试的复用性较低。</p>
		<br />
		<p>
				<b>2. </b>
				<b>白盒测试</b>
		</p>
		<p>白盒测试是指在测试时能够了解被测对象的结构，可以查阅被测代码内容的测试工作。它需要知道程序内部的设计结构及具体的代码实现，并以此为基础来设计测试用例。如下例程序代码：</p>
		<p>HRESULT Play( char* pszFileName ){</p>
		<p>if ( NULL == pszFileName ) return;</p>
		<p>if ( STATE_OPENED == currentState )</p>
		<p>{PlayTheFile();}</p>
		<p>return;}</p>
		<p>
		</p>
		<p>读了代码之后可以知道，先要检查一个字符串是否为空，然后再根据播放器当前的状态来执行相应的动作。可以这样设计一些测试用例：比如字符串（文件）为空的话会出现什么情况；如果此时播放器的状态是文件刚打开，会是什么情况；如果文件已经在播放，再调用这个函数会是什么情况。也就是说，根据播放器内部状态的不同，可以设计很多不同的测试用例。这些是在纯粹做黑盒测试时不一定能做到的事情。</p>
		<p>白盒测试的直接好处就是知道所设计的测试用例在代码级上哪些地方被忽略掉，它的优点是帮助软件测试人员增大代码的覆盖率，提高代码的质量，发现代码中隐藏的问题。</p>
		<p>白盒测试的缺点有：</p>
		<p>1）程序运行会有很多不同的路径，不可能测试所有的运行路径；</p>
		<p>2）测试基于代码，只能测试开发人员做的对不对，而不能知道设计的正确与否，可能会漏掉一些功能需求；</p>
		<p>3）系统庞大时，测试开销会非常大。</p>
		<br />
		<p>
				<b>3. </b>
				<b>基于风险的测试</b>
		</p>
		<p>基于风险的测试是指评估测试的优先级，先做高优先级的测试，如果时间或精力不够，低优先级的测试可以暂时先不做。有如下一个图，横轴代表影响，竖轴代表概率，根据一个软件的特点来确定：如果一个功能出了问题，它对整个产品的影响有多大，这个功能出问题的概率有多大？如果出问题的概率很大，出了问题对整个产品的影响也很大，那么在测试时就一定要覆盖到。对于一个用户很少用到的功能，出问题的概率很小，就算出了问题的影响也不是很大，那么如果时间比较紧的话，就可以考虑不测试。</p>
		<p>基于风险测试的两个决定因素就是：该功能出问题对用户的影响有多大，出问题的概率有多大。其它一些影响因素还有复杂性、可用性、依赖性、可修改性等。测试人员主要根据事情的轻重缓急来决定测试工作的重点。<br /></p>
<img src ="http://www.blogjava.net/matthew2006/aggbug/83610.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-26 14:52 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/26/83610.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何进行项目测试？--转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/26/83609.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sun, 26 Nov 2006 06:49:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/26/83609.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/83609.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/26/83609.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/83609.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/83609.html</trackback:ping><description><![CDATA[
		<p>一、前期准备<br />1）测试组与开发组协调，包括项目测试流程约定，测试组与开发组的协作活动安排等；<br />在项目前期，规划好测试组与开发组的协调工作，可以让测试人员与项目开发人员彼此了解在测试活动中的职责。为了规避项目部分风险，项目的测试组与开发组需要明确在项目的哪些重要活动需要提前沟通，例如需求的评审，汇总发现某周期测内仍遗留大量缺陷；对测试部门制定的相应测试流程中需要开发人员参与的部分，是否根据项目实际情况进行调整。</p>
		<p>2）项目需求及相关资源了解；<br />测试组组长（或测试经理）需要对项目的客户需求和项目本身要求进行了解，明确测试范围、测试指标、测试要点，测试所需软硬件环境等，为制定测试计划打好基础。</p>
		<p>二、制定测试计划<br />主要包括测试软硬件资源，人力资源，测试指标，粗略进度，采集的度量数据，风险，约定等。网络上有很多这方面的模板资料，建议定义好测试过程中要收集的度量数据，一般包括缺陷本身的属性，例如严重程度，功能类别，发现阶段，工作量，对应用例等；各周期内（例如以周为单位）缺陷的收敛情况（发现数量，解决数量，遗留数量），<br />阶段分布情况，缺陷存活情况等。</p>
		<p>三、编制测试用例<br />1）了解项目需求（客户需求与项目需求）<br />一方面为编制测试用例打好基础，另一方面可以找出需求中存在的问题。<br />2）明确公共用例<br />找出测试需求中，在编写用例时会出现重复的需求，编写公共用例，这样回减少后期用例编写工作量，也方便后期用例的维护。<br />3）明确手动测试用例与自动化测试用例范围<br />可以避免重复劳动，有些业务流程可以用自动化的用例来代替手动工作。<br />4）确定用例编写进度<br />5）正式编写<br />6）用例验证<br />7）明确测试用例执行顺序</p>
		<p>四、实施测试<br />1）确定实施进度。<br />2）搭建测试环境。<br />3）执行测试用例，记录用例执行结果，报告缺陷。<br />4）记录度量数据<br />5）维护测试用例</p>
		<p>五、测试总结<br />1）测试停止评估（参照测试用例执行情况，缺陷收敛情况，与测试指标偏差情况等）<br />2）测试总结报告<br />3）提交汇总度量数据，测试部门存档。<br /></p>
<img src ="http://www.blogjava.net/matthew2006/aggbug/83609.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-26 14:49 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/26/83609.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>