這是一個Maven提高篇的系列,包含有以下文章:
- Maven提高篇系列之(一)——多模塊 vs 繼承
- Maven提高篇系列之(二)——配置Plugin到某個Phase(以Selenium集成測試為例)
- Maven提高篇系列之(三)——使用自己的Repository(Nexus)
- Maven提高篇系列之(四)——使用Profile
- Maven提高篇系列之(五)——處理依賴沖突
- Maven提高篇系列之(六)——編寫自己的Plugin(本系列完)
持續交付要“自動化所有東西”,對於集成測試也是一樣。集成測試和單元測試相比需要更多的環境准備工作,包括測試數據的准備和啟動服務器等。在本篇中我們設想以下一種場景:
-
你開發了一個web應用,集成測試使用了Selenium,你希望通過一個Maven命令跑完所有的測試,包括集成測試。
Maven的plugin包含了一個或多個goal,每一個goal表示plugin的一個操作單位,在plugin開發中,一個goal通常對應於Java類的一個方法(Mojo的execute方法,請參考本系列之六)。一個goal可以默認綁定到Mavan的某個phase,比如Jar plugin的jar這個goal便默認綁定在了package這個phase上。當Maven執行到package時,Jar的jar goal將自動執行。當然,在默認情況下plugin的goal也可以不綁定在任何一個phase上,此時Maven將不做任何操作。但是,我們可以顯式地手動將某個plugin的某個goal綁定在一個phase中。
對於上面的場景,我們的解決方案是:在集成測試之前(對應Maven的phase為pre-integration-test),我們使用jetty-maven-plugin啟動web應用,在集成測試時通過Selenium訪問網站進行驗證,集成測試完畢之后(對應Maven的phase為post-integration-test),同樣使用jetty-maven-plugin關閉web應用。
Github示例代碼:https://github.com/davenkin/maven-plugin-binding.git
通過上一篇的方式創建一個web工程,向其中添加一個helloworld.html用於測試:
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
添加Selelium Webdriver集成測試如下:
public class SafariIntegrationTest { @Test public void testHelloWorldIndexPage() { WebDriver driver = new HtmlUnitDriver(); driver.get("http://localhost:8080/helloworld.html"); WebElement element = driver.findElement(By.tagName("h2")); assertThat(element.getText(), is("Hello World!")); } }
為了使用Selenium,我們需要將Selenium依賴加入pom.xml文件中:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.33.0</version>
</dependency>
接下來就可以配置jetty-maven-plugin了:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.12.v20130726</version>
<configuration>
<scanintervalseconds>0</scanintervalseconds>
<stopKey>stop</stopKey>
<stopPort>9999</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanintervalseconds>0</scanintervalseconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
可以看出,在pre-integration-test階段,我們調用了jetty-maven-plugin的run,此時web服務器啟動,在post-integration-test階段,我們調用了jetty-maven-plugin的stop來關閉web服務器。
但是這里有個問題,在運行mvn clean install時,Maven會先運行單元測試,再運行集成測試,並且在默認情況下這兩種測試都會運行以*Test.java結尾的測試類,結果在單元測試階段也會運行上面的SafariIntegrationTest,結果還沒有執行到集成測試階段就掛了。
此時,我們需要將單元測試和集成測試分開,Maven使用maven-surefire-plugin執行測試,我們可以先將SafariIntegrationTest排除在測試之外,這樣單元測試將不會運行該測試,然后在集成測試中,在將SafariIntegrationTest包含進來,此時我們需要修改maven-surefire-plugin的配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/unit/*Test.java</include>
</includes>
</configuration>
<executions>
<execution>
<id>surefire-it</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
現在運行mvn clean install,成功。在上面的例子中,我們使用了一個小trick,先將只有在unit目錄下的以*Test.java結尾的類看做測試類,此時不包含SafariIntegrationTest,而在itegration-test階段,我們將運行以*IntegrationTest.java結尾的測試類。
你可能還是不怎么放心,除非自己看到了實際的頁面為止。要達到這樣的目的,我們可以將SafariIntegrationTest中的:
WebDriver driver = new HtmlUnitDriver();//使用HtmlUnit
修改為:
WebDriver driver = new SafariDriver();//打開Safari瀏覽器
或者:
WebDriver driver = new InternetExplorerDriver();//打開IE瀏覽器
此時再運行mvn clean install,瀏覽器窗口將打開。