• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    JUnit 的最佳實踐

    發布: 2007-10-09 17:40 | 作者: 網絡轉載 | 來源: 網絡轉載 | 查看: 418次 | 進入軟件測試論壇討論

    領測軟件測試網 Techniques for building resilient, relocatable, multithreaded JUnit tests
       一項靈活的、可重定位的多線程JUnit測試技術   
       作者 Andy Schneider
       譯者 雷云飛 javawebstart Barret gstian [AKA]
       校對 gstian [AKA]
       Summary
       摘要   
       Extreme Programming's rise in popularity among the Java community has prompted more development teams to use JUnit: a simple test framework for building and executing unit tests. Like any toolkit, JUnit can be used effectively and ineffectively. In this article, Andy Schneider discusses good and bad ways to use JUnit and provides practical recommendations for its use by development teams. In addition, he explains simple mechanisms to support:   
       Java社區里面流行的編程熱的不斷升溫使越來越多的開發團隊使用 JUnit進行測試。JUnit 是一種構造和進行單元測試的簡便的測試框架。就象所有的工具包一樣,JUnit 可以被高效的使用,也可以被低效的使用。在這篇文章種,Andy Schneider討論了JUnit 的高效和低效的使用方法,并且為開發團隊提供了實用的JUnit使用建議。另外,他提供了幾種簡單的機制來解釋兩種方法的差別:   
       Automatic construction of composite tests   
       組合測試的自動構件   
       Multithreaded test cases   
       多線程測試用例   
       This article assumes some familiarity with JUnit. (4,000 words)   
       閱讀本篇文章,需要您對JUnit略知一二。   
       JUnit is a typical toolkit: if used with care and with recognition of its idiosyncrasies, JUnit will help to develop good, robust tests. Used blindly, it may produce a pile of spaghetti instead of a test suite. This article presents some guidelines that can help you avoid the pasta nightmare. The guidelines sometimes contradict themselves and each other -- this is deliberate. In my experience, there are rarely hard and fast rules in development, and guidelines that claim to be are misleading.   
       JUnit是一個有特色的工具包:熟知它的特性的情況下并細心的使用,它在你開發優良的健壯的測試上市有幫助的。如果被盲目的使用,它可能就像一堆意大利面條,而不是測試集。本文給出了一些可以幫助你避免這些生面團惡夢的指導方針。這些指導方針有時看起來會相互矛盾----這是故意的。以我的經驗,在開發中很少有硬性而方便的規則。任何聲稱是這種規則的指導方針都是誤導。   
       We'll also closely examine two useful additions to the developer's toolkit:   
       我們同時還將深入檢查開發者的工具包里的兩個有用的附加物:   
       A mechanism for automatically creating test suites from classfiles in part of a filesystem   
       一種可以從部分文件系統里面自動創建測試集的機制   
       A new TestCase that better supports tests in multiple threads   
       一種更好支持多線程的新測試用例。   
       When faced with unit testing, many teams end up producing some kind of testing framework. JUnit, available as open source, eliminates this onerous task by providing a ready-made framework for unit testing. JUnit, best used as an integral part of a development testing regime, provides a mechanism that developers can use to consistently write and execute tests. So, what are the JUnit best practices?   
       當面對單元測試時,許多團隊都會自己去完成某種測試框架。JUnit做為一種開放軟件,通過為單元測試提供一種現成的測試框架,來消除這種繁重的任務。JUnit作為一個開發測試體制整體中的一部分給開發者提供了一種可以一致地編寫和執行測試的機制。既然如此,那么,什么是JUnit的最佳實踐?   
       Do not use the test-case constructor to set up a test case   
       不要使用測試用例構造器來創建一個測試用例
       Setting up a test case in the constructor is not a good idea. Consider:   
       使用構造器來建立一個測試用例并不是個好主意,例如:   
       public class SomeTest extends TestCase   
       public SomeTest (String testName) {   
       super (testName);   
       // Perform test set-up   
       }   
       }   
       Imagine that while performing the setup, the setup code throws an IllegalStateException. In response, JUnit would throw an AssertionFailedError, indicating that the test case could not be instantiated. Here is an example of the resulting stack trace:   
       想象一下當執行安裝時,代碼拋出一個IllegalStateException異常。做為回應,JUnit也會拋出一個AssertionFailedError異常來指示測試用例無法實例化。下面是一個堆棧跟蹤結果示例:   
       junit.framework.AssertionFailedError: Cannot instantiate test case: test1 at   
       junit.framework.Assert.fail(Assert.java:143) at   
       junit.framework.TestSuite$1.runTest(TestSuite.java:178) at   
       junit.framework.TestCase.runBare(TestCase.java:129) at   
       junit.framework.TestResult$1.protect(TestResult.java:100) at   
       junit.framework.TestResult.runProtected(TestResult.java:117) at   
       junit.framework.TestResult.run(TestResult.java:103) at   
       junit.framework.TestCase.run(TestCase.java:120) at   
       junit.framework.TestSuite.run(TestSuite.java, Compiled Code) at   
       junit.ui.TestRunner$12.run(TestRunner.java:429)   
       This stack trace proves rather uninformative; it only indicates that the test case could not be instantiated. It doesn't detail the original error's location or place of origin. This lack of information makes it hard to deduce the exception's underlying cause.   
       這個堆棧跟蹤沒有提供多少有價值的信息。它只是表明測試用例不能被實例化。它并沒有初始化時產生錯誤的錯誤位置和錯誤來源的詳細信息。信息的缺乏使得推斷該異常出現的原因變得困難。   
       Instead of setting up the data in the constructor, perform test setup by overriding setUp(). Any exception thrown within setUp() is reported correctly. Compare this stack trace with the previous example:   
       放棄在構造器中創建數據,通過重載setUp()來執行測試創建,。任何在setUp()中產生的異常都會被準確的報告。與前一個例子對照,比較下面的堆棧跟蹤:   
       java.lang.IllegalStateException: Oops at bp.DTC.setUp(DTC.java:34) at   
       junit.framework.TestCase.runBare(TestCase.java:127) at   
       junit.framework.TestResult$1.protect(TestResult.java:100) at   
       junit.framework.TestResult.runProtected(TestResult.java:117) at   
       junit.framework.TestResult.run(TestResult.java:103)   
       ...   
       This stack trace is much more informative; it shows which exception was thrown (IllegalStateException) and from where. That makes it far easier to explain the test setup's failure.   
       這個堆棧跟蹤含有更多的信息量。它表明了異常類型(IllegalStateException), 以及產生位置。這使得可以更容易解釋為何測試建立失敗。   
       Don't assume the order in which tests within a test case run   
       不要推測一個測試用例運行中各測試的執行順序
       You should not assume that tests will be called in any particular order. Consider the following code segment:   
       你不應該認為各測試用例會按照任何特定順序被調用?紤]下面的代碼片斷:   
       public class SomeTestCase extends TestCase {   
       public SomeTestCase (String testName) {   
       super (testName);   
       }   
       public void testDoThisFirst () {   
       ...   
       }   
       public void testDoThisSecond () {   
       }   
       }   
       In this example, it is not certain that JUnit will run these tests in any specific order when using reflection. Running the tests on different platforms and Java VMs may therefore yield different results, unless your tests are designed to run in any order. Avoiding temporal coupling will make the test case more robust, since changes in the order will not affect other tests. If the tests are coupled, the errors that result from a minor update may prove difficult to find.   
       在這個例子中,當使用映射時,JUnit將按照何種順序執行這些測試并不能確定。在不同的平臺及Java VM上,可能產生不同的結果,除非你的測試被事先設計為按某種順序執行。由于執行順序的改變不會影響其它測試,避免這種短暫的耦合使得你的測試用例更加健壯。如果測試耦合在一起,由于一個小變動引起的錯誤也許會難于發現。   
       In situations where ordering tests makes sense -- when it is more efficient for tests to operate on some shared data that establish a fresh state as each test runs -- use a static suite() method like this one to ensure the ordering:   
       在某些情況下,測試的順序還是有意義的----例如,測試們可以使用一些共享數據時來提高效率。這些共享數據對于每個測試運行時都會建立一個新的狀態。----可以使用一個靜態的 suite() 方法來保證執行順序,如下:   
       public static Test suite() {   
       suite.addTest(new SomeTestCase ("testDoThisFirst");   
       suite.addTest(new SomeTestCase ("testDoThisSecond");   
       return suite;   
       }
       Test cases that have side effects exhibit two problems:   
       帶有副作用的測試用例會出現下面兩個問題:   
       They can affect data that other test cases rely upon   
       它們會影響其他測試用例所依賴的數據   
       You cannot repeat tests without manual intervention   
       你不能在沒有手工干預的情況下重復測試   
       In the first situation, the individual test case may operate correctly. However, if incorporated into a TestSuite that runs every test case on the system, it may cause other test cases to fail. That failure mode can be difficult to diagnose, and the error may be located far from the test failure.   
       在第一種情況下,獨立的測試用例也許可以正確的執行,然而,當它們被置入一個執行 該系統中所有測試的測試集時,可能導致其他測試用例失敗。但這種失敗的做法很難 診斷出來,錯誤也許離失敗的地方很遠。   
       In the second situation, a test case may have updated some system state so that it cannot run again without manual intervention, which may consist of deleting test data from the database (for example). Think carefully before introducing manual intervention. First, the manual intervention will need to be documented. Second, the tests could no longer be run in an unattended mode, removing your ability to run tests overnight or as part of some automated periodic test run.   
       在第二種情況下,一個測試用例可能運行后更改了系統狀態,以至于它不能在沒有手工干預 的情況下被再次執行。例如,這有可能是從數據庫中刪除了測試數據造成的。在手工 干預之前,仔細的考慮下面兩點:首先,手工干預應該被記錄在文檔當中,其次,這種測試不 能在無人監控的情況下被執行,應該去掉它們通宵執行測試或者作為自動運行的周期性測試的一部分的能力.   
       Call a superclass's setUp() and tearDown() methods when subclassing
       子類化的時候,調用父類的 setUp() 方法和 tearDown() 方法
       When you consider:   
       考慮如下情況:   
       public class SomeTestCase extends AnotherTestCase {   
       // A connection to a database   
       private Database theDatabase;   
       public SomeTestCase (String testName) {   
       super (testName);   
       }   
       public void testFeatureX () {   
       ...   
       }   
       public void setUp () {   
       // Clear out the database   
       theDatabase.clear ();   
       }   
       }   
       Can you spot the deliberate mistake? setUp() should call super.setUp() to ensure that the environment defined in AnotherTestCase initializes. Of course, there are exceptions: if you design the base class to work with arbitrary test data, there won't be a problem.   
       你能發現隱藏其中的那個需要深思的錯誤嗎?setUp()方法應該調用父類的setUp()方法以保證能夠初始化在父類AnotherTestCase 中定義的測試環境。當然,這也并不是絕對的--如果父類設計成可以通用的基類的話,那么,以上就不是一個問題。   
       Do not load data from hard-coded locations on a filesystem   
       不要從文件系統里那些代碼已固定的位置加載數據   
       Tests often need to load data from some location in the filesystem. Consider the following:   
       測試經常要從文件系統中讀入數據,如下:   
       public void setUp () {   
       FileInputStream inp ("C:\\TestData\\dataSet1.dat");   
       ...   
       }   
       The code above relies on the data set being in the C:\TestData path. That assumption is incorrect in two situations:   
       上面這段代碼依賴于C:\TestDate中的數據。在下面2種情況下,上面的假設會出現如下問題:   
       A tester does not have room to store the test data on C: and stores it on another disk   
       可能在C盤沒有足夠的空間存儲測試數據,而把它存在其它的磁盤上   
       The tests run on another platform, such as Unix
       測試案例可能運行在另外的平臺上,比如Unix   
       One solution might be:   
       以下是一種解決方案:   
       public void setUp () {   
       FileInputStream inp ("dataSet1.dat");   
       ...   
       }   
       However, that solution depends on the test running from the same directory as the test data. If several different test cases assume this, it is difficult to integrate them into one test suite without continually changing the current directory.   
       但是,上面的解決方案是把測試數據放在運行測試案例的目錄中,如果把這樣的幾個測試案例集成起來作為測試集來運行的話,只有測試集在運行過程中不斷的改變當前目錄才行。   
       To solve the problem, access the dataset using either Class.getResource() or Class.getResourceAsStream(). Using them, however, means that resources load from a location relative to the class's origin.   
       要解決這個問題,可以使用Class.getResource()或者Class.getResourceAsStream()這種訪問資源的形式來訪問數據,它們都是從類的相對路徑來訪問資源的。   
       Test data should, if possible, be stored with the source code in a configuration management (CM) system. However, if you're using the aforementioned resource mechanism, you'll need to write a script that moves all the test data from the CM system into the classpath of the system under test. A less ungainly approach is to store the test data in the source tree along with the source files. With this approach, you need a location-independent mechanism to locate the test data within the source tree. One such mechanism is a class. If a class can be mapped to a specific source directory, you could write code like this:   
       如果可能的話,測試數據應該和源程序一起存放到配置管理系統中。如果使用前面提到的訪問資源的形式,就要自己寫腳本來把所有的測試數據從配置管理系統中取出來加入要測試案例的classpath中。還有一種方法是把測試數據和源程序存放在一起,使用和位置無關的方法來查找測試數據。以類為例,如果類能夠被映射到一個特定的目錄,相應的代碼可以如下:   
       InputStream inp = SourceResourceLoader.getResourceAsStream (this.getClass (), "dataSet1.dat");   
       Now you must only determine how to map from a class to the directory that contains the relevant source file. You can identify the root of the source tree (assuming it has a single root) by a system property. The class's package name can then identify the directory where the source file lies. The resource loads from that directory. For Unix and NT, the mapping is straightforward: replace every instance of '.' with File.separatorChar.   
       現在要考慮的是怎么把一個類映射到包含相應源文件的目錄?梢酝ㄟ^系統屬性來設置源文件根目錄。類的包名可以標志源文件的存放位置。在Unix和NT上,這種映射是直接的:把'.'替換成為File.separatorChar就可以了。   
       Keep tests in the same location as the source code   
       把測試案例和源文件放在一起
       If the test source is kept in the same location as the tested classes, both test and class will compile during a build. This forces you to keep the tests and classes synchronized during development. Indeed, unit tests not considered part of the normal build quickly become dated and useless.   
       如果測試案例和要測試的代碼放在一起,那么可以同時對這兩者編譯。這樣可以保證在開發過程中測試和代碼保持同步。實際上,不在正常的版本中的單元測試馬上會變的過時、無用。   
       Name tests properly
       正確命名測試案例   
       Name the test case TestClassUnderTest. For example, the test case for the class MessageLog should be TestMessageLog. That makes it simple to work out what class a test case tests. Test methods' names within the test case should describe what they test:   
       給測試案例起名TestClassUnderTest。例如,類MessageLog的測試案例的名字應該是TestMessageLog。這樣可以很容易的看出是對哪個類進行測試。同時,測試案例的方法應該清楚的表明要測什么:   
       testLoggingEmptyMessage()   
       testLoggingNullMessage()   
       testLoggingWarningMessage()   
       testLoggingErrorMessage()   
       Proper naming helps code readers understand each test's purpose.   
       正確的命名可以幫助別人理解每個測試的目的。   
       Ensure that tests are time-independent
       保證測試是和時間無關的   
       Where possible, avoid using data that may expire; such data should be either manually or programmatically refreshed. It is often simpler to instrument the class under test, with a mechanism for changing its notion of today. The test can then operate in a time-independent manner without having to refresh the data.   
       只要可能,避免使用可能過期的數據;這樣的數據要么手工,要么由程序來刷新。在測試下建立一個類經常需要更簡化些,要用一種可以與現在的思想保持同步的機制.這樣,測試案例就可以和時間無關,不需要刷新數據。   
       Consider locale when writing tests
       寫測試時考慮地址的影響   
       Consider a test that uses dates. One approach to creating dates would be:   
       考慮使用日期的一個測試案例。一種創建日期的方法:   
       Date date = DateFormat.getInstance ().parse ("dd/mm/yyyy");   
       There is no guarantee in the JUnit API documentation as to the order your tests will be called in, because JUnit employs a Vector to store tests. However, you can expect the above tests to be executed in the order they were added to the test suite.   
       在JUnit API 文檔中并沒有保證你的測試被調用的順序,因為JUnit使用V一個區段來存放測試。 然而,你可以保證上面的測試按照它們被加入測試集的順序被執行。   
       Avoid writing test cases with side effects   
       避免寫帶有副作用的測試用例
       Unfortunately, that code doesn't work on a machine with a different locale. Therefore, it would be far better to write:   
       不幸的是,這段代碼在不同的機器上不能正常的運行。因此,可以換用下面較好的方式:   
       Calendar cal = Calendar.getInstance ();   
       Cal.set (yyyy, mm-1, dd);   
       Date date = Calendar.getTime ();   
       The second approach is far more resilient to locale changes.   
       第二中方法可以更靈活的適應地址的改變。   
       Utilize JUnit's assert/fail methods and exception handling for clean test code
       利用JUnit's的assert/fail方法和異常機制創建干凈的代碼   
       Many JUnit novices make the mistake of generating elaborate try and catch blocks to catch unexpected exceptions and flag a test failure. Here is a trivial example of this:   
       許多初學者可能會精心設計一些異常捕捉來捕捉異常,并標志測試出現錯誤。如下:   
       public void exampleTest () {   
       try {   
       // do some test   
       } catch (SomeApplicationException e) {   
       fail ("Caught SomeApplicationException exception");   
       }   
       }   
       JUnit automatically catches exceptions. It considers uncaught exceptions to be errors, which means the above example has redundant code in it.   
       JUnit可以自動的捕捉異常,把沒有截獲的異?醋麇e誤,所以,上面的代碼有冗余代碼。   
       Here's a far simpler way to achieve the same result:   
       以下以一種更簡潔的方式實現上面的例子:   
       public void exampleTest () throws SomeApplicationException {   
       // do some test   
       }   
       In this example, the redundant code has been removed, making the test easier to read and maintain (since there is less code).   
       在此,除去了冗余的代碼,使得測試易讀易維護(因為代碼很少)。   
       Use the wide variety of assert methods to express your intention in a simpler fashion. Instead of writing:   
       使用廣泛的多樣性的有效方法來表達你的意圖。不應該:   
       assert (creds == 3);   
       Write:   
       而是:   
       assertEquals ("The number of credentials should be 3", 3, creds);   
       The above example is much more useful to a code reader. And if the assertion fails, it provides the tester with more information. JUnit also supports floating point comparisons:   
       上面的代碼讓人很容易的讀懂,并且即使上面的維護失敗,可以提供給測試者更多的信息。JUnit同樣支持浮點數的比較:   
       assertEquals ("some message", result, expected, delta);   
       When you compare floating point numbers, this useful function saves you from repeatedly writing code to compute the difference between the result and the expected value.   
       當比較浮點類型的數據時,可以不必再寫同樣功能的代碼。   
       Use assertSame() to test for two references that point to the same object. Use assertEquals() to test for two objects that are equal.   
       要測試兩個引用是否指向同一個對象,使用assertSame()方法;要測試兩個對象是否相等,使用assertEquals()方法   
       Document tests in javadoc
       javadoc下的文檔測試   
       Test plans documented in a word processor tend to be error-prone and tedious to create. Also, word-processor-based documentation must be kept synchronized with the unit tests, adding another layer of complexity to the process. If possible, a better solution would be to include the test plans in the tests' javadoc, ensuring that all test plan data reside in one place.   
       在一個字處理器里創建需要歸檔的測試計劃易于出現錯誤且單調乏味。另外,基于字處理器的文件必須與單元測試保持同步,這給處理過程增加了額外一層的復雜性。如果可能,更好的解決方法是將測試計劃包括在測試的javadoc,確保所有的測試計劃數據保存在一個地方。   
       Avoid visual inspection
       避免目視檢查   
       Testing servlets, user interfaces, and other systems that produce complex output is often left to visual inspection. Visual inspection -- a human inspecting output data for errors -- requires patience, the ability to process large quantities of information, and great attention to detail: attributes not often found in the average human being. Below are some basic techniques that will help reduce the visual inspection component of your test cycle.   
       測試servlets,用戶界面,和其他產生復雜輸出的系統通常采用目視檢查。目視檢查--一個人為了發現錯誤檢查輸出的數據--需要耐心,處理大量信息的能力,以及對細節的洞察力:這些通常不會是一般人身上所具備的。以下是一些基本的技術可以用來幫助減少你的測試周期中目視檢查。   
       Swing
       Swing   
       When testing a Swing-based UI, you can write tests to ensure that:   
       當測試一個基于Swing的用戶界面時,你可以寫一些測試以保證:   
       All the components reside in the correct panels   
       所有的構件都在適當的面板里   
       You've configured the layout managers correctly   
       確保正確配置了版式管理器   
       Text widgets have the correct fonts   
       Text widgets(文字集)里有正確的字體   
       A more thorough treatment of this can be found in the worked example of testing a GUI, referenced in the Resources section.
       這方面更詳細的處理方式可以在一個測試某GUI的成功例子中找到,參考資料章節。   
       XML
       XML   
       When testing classes that process XML, it pays to write a routine that compares two XML DOMs for equality. You can then programmatically define the correct DOM in advance and compare it with the actual output from your processing methods.   
       當測試處理XML的類時,寫一個程序比較兩個XML DOM是否相等。這樣你可以預先精確地定義正確的DOM并且與使用你的處理方法得出的實際結果相比較。

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/

    TAG: juint


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備2023014753號-2
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>