单元和集成测试的代码覆盖率
首先,所有的源代碼都可以在github上找到: https : //github.com/activelylazy/coverage-example 。 我將顯示關鍵片段,但顯然有很多細節被忽略了(希望如此)不相關。
示例應用
該示例應用程序不是打破傳統,而是一個簡單的,即使有點人為的問候世界:
怎么運行的
起始頁面是指向hello world頁面的簡單鏈接:
<h1>Example app</h1> <p>See the <a id="messageLink" href="helloWorld.html">message</a></p>Hello World頁面僅顯示以下消息:
<h1>Example app</h1> <p id="message"><c:out value="${message}"/></p>hello world控制器渲染視圖,并傳遞消息:
public class HelloWorldController extends ParameterizableViewController {// Our message factoryprivate MessageFactory messageFactory;@Overrideprotected ModelAndView handleRequestInternal(HttpServletRequest request,HttpServletResponse response) throws Exception {// Get the success viewModelAndView mav = super.handleRequestInternal(request, response);// Add our messagemav.addObject("message",messageFactory.createMessage());return mav;}@Autowiredpublic void setMessageFactory(MessageFactory messageFactory) {this.messageFactory = messageFactory;} }最后,MessageFactory僅返回硬編碼的消息:
public String createMessage() {return "Hello world"; }單元測試
我們定義了一個簡單的單元測試,以驗證MessageFactory的行為是否符合預期:
public class MessageFactoryTest {// The message factoryprivate MessageFactory messageFactory;@Testpublic void testCreateMessage() {assertEquals("Hello world",messageFactory.createMessage());}@Autowiredpublic void setMessageFactory(MessageFactory messageFactory) {this.messageFactory = messageFactory;} }建立
一個基本的maven pom文件足以構建此文件并運行單元測試。 至此,我們有了一個正在運行的應用程序,并對我們可以構建和運行的核心功能(例如它)進行了單元測試。
<project><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>helloworld</artifactId><packaging>war</packaging><version>1.0-SNAPSHOT</version><name>helloworld Maven Webapp</name><build><finalName>helloworld</finalName></build><dependencies>...omitted...</dependencies> </project>代碼覆蓋率
現在,我們集成Emma,以便獲得一些代碼覆蓋率報告。 首先,我們定義一個新的Maven配置文件,這使我們可以控制是否在任何給定的版本上使用emma。
<profile><id>with-emma</id><build><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>emma-maven-plugin</artifactId><inherited>true</inherited><executions><execution><id>instrument</id><phase>process-test-classes</phase><goals><goal>instrument</goal></goals></execution></executions></plugin></plugins></build> </profile>這只是在Maven“過程測試類”階段調用“儀器”目標。 即,一旦我們編譯了類文件,請使用emma對其進行檢測。 我們可以通過使用新的配置文件調用Maven來運行它:
mvn clean install -Pwith-emma 構建完成后,我們可以運行Emma生成代碼覆蓋率報告:
在Windows上:
在Linux上:
java -cp ~/.m2/repository/emma/emma/2.0.5312/emma-2.0.5312.jar emma report -r xml,html -in coverage.ec -in target/coverage.em現在,我們可以在coverage / index.html中查看HTML覆蓋率報告。 在這一點上,它表明我們有50%的測試覆蓋率(按類)。 MessageFactory已完全覆蓋,但是HelloWorldController根本沒有任何測試。
整合測試
為了測試我們的控制器和JSP,我們將使用WebDriver創建一個簡單的集成測試。 這是一個恰巧啟動瀏覽器的JUnit測試。
public class HelloWorldIntegrationTest {// The webdriverprivate static WebDriver driver;@BeforeClasspublic static void initWebDriver() {driver = new FirefoxDriver();}@AfterClasspublic static void stopSeleniumClent() {try {driver.close();driver.quit();} catch( Throwable t ) {// Catch error & log, not critical for testsSystem.err.println("Error stopping driver: "+t.getMessage());t.printStackTrace(System.err);}}@Testpublic void testHelloWorld() {// Start from the homepagedriver.get("http://localhost:9080/helloworld/");HomePage homePage = new HomePage(driver);HelloWorldPage helloWorldPage = homePage.clickMessageLink();assertEquals("Hello world",helloWorldPage.getMessage());} } 第4-18行只是在測試之前啟動Web驅動程序,并在測試完成后將其關閉(關閉瀏覽器窗口)。
在第22行,我們使用硬編碼的URL導航到主頁。
在第23行,我們初始化主頁的Web Driver 頁面對象 。 這封裝了頁面工作方式的所有細節,從而使測試可以與頁面進行功能上的交互,而無需擔心機制(使用哪些元素等)。 在第24行,我們使用主頁對象單擊“消息”鏈接; 這將導航到hello world頁面。 在第25行,我們確認Hello World頁面上顯示的消息是我們期望的。 注意:我正在使用頁面對象將測試規范 (做什么)與測試實現 (如何做)分開。 有關為什么這很重要的更多信息,請參見防止測試變脆 。
主頁
主頁對象非常簡單:
public HelloWorldPage clickMessageLink() {driver.findElement(By.id("messageLink")).click();return new HelloWorldPage(driver); }HelloWorldPage
hello world頁面同樣簡單:
public String getMessage() {return driver.findElement(By.id("message")).getText(); }運行集成測試
要在我們的Maven構建過程中運行集成測試,我們需要進行一些更改。 首先,我們需要從單元測試階段中排除集成測試:
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId>...<configuration>...<excludes><exclude>**/*IntegrationTest.java</exclude><exclude>**/common/*</exclude></excludes></configuration> </plugin>然后,我們定義一個新的配置文件,因此我們可以選擇運行集成測試:
<profile><id>with-integration-tests</id><build><plugins><plugin><groupId>org.mortbay.jetty</groupId><artifactId>maven-jetty-plugin</artifactId><version>6.1.22</version><configuration><scanIntervalSeconds>5</scanIntervalSeconds><stopPort>9966</stopPort><stopKey>foo</stopKey><connectors><connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"><port>9080</port><maxIdleTime>60000</maxIdleTime></connector></connectors></configuration><executions><execution><id>start-jetty</id><phase>pre-integration-test</phase><goals><goal>run</goal></goals><configuration><daemon>true</daemon></configuration></execution><execution><id>stop-jetty</id><phase>post-integration-test</phase><goals><goal>stop</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.5</version><inherited>true</inherited><executions><execution><id>integration-tests</id><phase>integration-test</phase><goals><goal>test</goal></goals><configuration><excludes><exclude>**/common/*</exclude></excludes><includes><include>**/*IntegrationTest.java</include></includes></configuration></execution></executions></plugin></plugins></build> </profile> <個人資料><id> with-integration-tests </ id>
<內部版本>
<插件>
<插件>
<groupId> org.mortbay.jetty </ groupId>
<artifactId> maven-jetty-plugin </ artifactId>
<version> 6.1.22 </ version>
<配置>
<scanIntervalSeconds> 5 </ scanIntervalSeconds>
<stopPort> 9966 </ stopPort>
<stopKey> foo </ stopKey>
<連接器>
<連接器實現=” org.mortbay.jetty.nio.SelectChannelConnector”>
<port> $ {test.server.port} </ port>
<maxIdleTime> 60000 </ maxIdleTime>
</ connector>
</ connectors>
</ configuration>
<執行>
<執行>
<id>開始碼頭</ id>
<phase>集成前測試</ phase>
<目標>
<goal>運行</ goal>
</ goals>
<配置>
<daemon> true </ daemon>
</ configuration>
</ execution>
<執行>
<id>停止碼頭</ id>
<phase>集成后測試</ phase>
<目標>
<goal>停止</ goal>
</ goals>
</ execution>
</ executions>
</ plugin>
<插件>
<groupId> org.apache.maven.plugins </ groupId>
<artifactId> maven-surefire-plugin </ artifactId>
<version> 2.5 </ version>
<inherited> true </ inherited>
<執行>
<執行>
<id>集成測試</ id>
<phase>集成測試</ phase>
<目標>
<goal>測試</ goal>
</ goals>
<配置>
<排除>
<exclude> ** / common / * </ exclude>
</ excludes>
<包括>
<include> ** / * IntegrationTest.java </ include>
</ includes>
</ configuration>
</ execution>
</ executions>
</ plugin>
</ plugins>
</ build>
</ profile>
這可能看起來很復雜,但實際上我們只是在配置碼頭來運行我們的集成測試。 然后配置如何自行運行集成測試。
在9-19行中,配置碼頭-要繼續運行的港口以及如何停止碼頭。
21-30行配置了碼頭以在Maven構建的“集成前測試”階段運行。 31-37行配置了要在Maven構建的“集成后測試”階段停止的碼頭。 在第40-62行中,我們再次使用maven-surefire-plugin,這次是在構建的“集成測試”階段運行,僅運行我們的集成測試類。
我們可以使用以下命令運行此構建:
mvn clean install -Pwith-emma -Pwith-integration-tests這將構建所有內容,運行單元測試,構建戰爭,啟動碼頭以主持戰爭,運行我們的集成測試(在其余運行時您將看到一個Firefox窗口彈出),然后關閉碼頭。 因為戰爭是通過檢測類構建的,所以在我們運行集成測試時,Emma還會跟蹤代碼覆蓋率。
現在,我們可以構建應用程序,運行單元測試和集成測試,收集組合的代碼覆蓋率報告。 如果我們重新運行emma報告并檢查代碼覆蓋率,我們現在將看到我們具有100%的測試覆蓋率-因為控制器也已通過測試覆蓋。
問題
有哪些未解決的問題,可以做哪些進一步的擴展?
- 該構建會生成一個已檢測到的WAR –這意味著您需要運行第二個構建(沒有emma)才能獲得可用于生產的構建。
- 集成測試對Jetty配置為啟動的端口進行硬編碼。 意味著測試不能直接在Eclipse中運行。 可以傳入此端口,默認為8080,這樣集成測試就可以通過maven構建在Eclipse中運行。
- 在構建服務器上運行時,您可能不希望Firefox隨機彈出(如果甚至安裝了X); 因此,運行xvfb是一個好主意。 可以將maven設置為在集成測試之前和之后啟動和停止xvfb。
參考: 單元和集成測試的代碼覆蓋范圍以及Actively Lazy博客的JCG合作伙伴 Dave提供的信息
相關文章 :- 任何軟件開發公司應存在的服務,實踐和工具,第1部分
- 任何軟件開發公司應存在的服務,實踐和工具,第2部分
- 這是在您的業務邏輯之前!
- 您的代碼中有幾個錯誤?
- 使用FindBugs產生更少的錯誤代碼
- Java工具:源代碼優化和分析
- 每個程序員都應該知道的事情
- 為什么自動化測試可以提高您的開發速度
翻譯自: https://www.javacodegeeks.com/2011/10/code-coverage-with-unit-integration.html
總結
以上是生活随笔為你收集整理的单元和集成测试的代码覆盖率的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每个人都知道MVC…
- 下一篇: ROG RTX 4090 猛禽新世纪福音