3. 單元測試實踐——構(gòu)建優(yōu)秀
3.1 在組織中引入單元測試
在一個組織中成功的引入測試驅(qū)動開發(fā)和單元測試并集成到該組織的文化中冒掌,對該組織的發(fā)展和團隊的效率將會有極大的提升崎淳。然后有時候這個引入會失敗幻锁,成功的組織則存在一些共性的東西畜隶,我們在這一節(jié)將探討一下如何增加引入單元測試的成功率吃挑。
在任何類型的組織中徐裸,改變?nèi)藗兊牧?xí)慣多半與心理學(xué)有關(guān)船万,而并非是技術(shù)問題刻撒。人們不喜歡變化,而且變化常常伴隨著很多的FUD(fear, uncertainty, and doubt——害怕耿导、不確定性和懷疑)声怔。于是如何說服組織成員或者讓組織接受新的變化,并不是一件容易和輕松的事情舱呻。
-
怎樣成為變革推動者
開始實施變革之前醋火,人們會開始對它們關(guān)心的事情提出棘手的問題,例如這樣做會“浪費”多少時間箱吕?這對于開發(fā)人員來說意味著什么芥驳?我們怎么知道它有效呢?這些問題可以嘗試用下面的成功的方式進行解決茬高。你會發(fā)現(xiàn)兆旬,當你能夠回答這些問題,并說服組織中的其它人怎栽,會對組織的變革提供非常大的幫助丽猬。
這里有一些幫助的小提示:
- 選擇較小的團隊
- 新建子團隊
- 考慮項目的可行性
此外,在變革中需要找到阻礙者婚瓜,并尋找到它們不愿意進行單元測試的嘗試的原因所在宝鼓,加以解決。此外可以考慮賦予它們?nèi)碌穆氊?zé)巴刻,會讓它們覺得被依賴而且對組織有意義愚铡。
?
-
成功之路
組織或者團隊開始改變流程主要有兩個方式:自下而上或者自上而下。
- 自下而上:先說服程序員胡陪,使得程序員采納并且提倡沥寥,然后產(chǎn)生組織的變革,最終說服管理層接受柠座。
- 自上而下:經(jīng)理通過給團隊做一個演示來開始實施邑雅,或者使用自己的權(quán)力進行推動變革。
代碼的完整性妈经,Code Integrity
這個術(shù)語淮野,通常意味著代碼做它該做的事捧书,而團隊知道代碼不能做哪些事。
代碼的完整性包括如下實踐:
- 自動化構(gòu)建
- 持續(xù)集成
- 單元測試與測試驅(qū)動開發(fā)
- 代碼一致性和商定的質(zhì)量標準
- 盡量快速的修復(fù)缺陷
為了“我們的代碼完整性很好”這個目標骤星,也可以開始如上的實踐经瓷。
?
-
鎖定目標
沒有目標,將會很難衡量改變洞难,并且與他人交流舆吮。可以考慮下面的目標
- 提高代碼測試覆蓋率
- 提高相對代碼改動量的測試覆蓋率
- 減少重復(fù)出現(xiàn)的缺陷
- 減少修復(fù)缺陷的平均時間
3.2 使用 Maven 運行 JUnit 單元測試
-
Maven的功能與安裝
Maven 是一個用于項目構(gòu)建的工具队贱,通過它便捷的管理項目的生命周期色冀。同時 Maven 不只是一個簡單的項目構(gòu)建工具,還是一個依賴管理工具和項目信息管理工具柱嫌。它提供了中央倉庫锋恬,能幫我們自動下載構(gòu)建。
在之前的課程中慎式,我們使用 IDEA 工具伶氢,通過直接導(dǎo)入 JUnit 的
*.jar
包文件,進行單元測試的構(gòu)建的瘪吏。在這里我們繼續(xù)使用 Maven 作為構(gòu)建工具癣防,來構(gòu)建 JUnit 單元測試項目。首先掌眠,不要相信任何 IDE(Integration Development Environment蕾盯,集成開發(fā)工具)中自帶的 Maven 插件,包括 IDEA自帶的蓝丙。那么我們需要安裝 Maven级遭。
具體的安裝步驟如下:
-
檢查 JDK 的安裝
在安裝 Maven 之前,首先要確認已經(jīng)正確的安裝了 JDK渺尘。Maven 可以運行在 JDK 1.4 以及以上的版本挫鸽。目前的 JDK 1.8 的版本是可以的。需要下載 JDK 并進行安裝鸥跟。安裝好 JDK 以后丢郊,需要檢查 %JAVA_HOME% 的環(huán)境變量是否設(shè)定。
輸入 cmd | 打開 Windows 命令行医咨, 輸入
echo %JAVA_HOME%
Microsoft Windows [Version 10.0.14393] (c) 2016 Microsoft Corporation. All rights reserved. C:\Users\xxx>echo %JAVA_HOME% C:\Program Files\Java\jdk1.8.0_66
?
-
下載并安裝 Maven
Maven 可以免費在官網(wǎng)下載并安裝枫匾。打開 Manve 的下載頁面,下載針對所用平臺的對應(yīng)的版本拟淮,然后在 C 盤解壓即可干茉。
Maven 的下載地址:https://maven.apache.org/download.cgi
解壓以后,需要設(shè)定 Windows 的環(huán)境變量很泊。
- %M2_HOME%:在系統(tǒng)變量添加角虫,路徑為安裝的 Maven 的根目錄沾谓,例如
C:\Apache\apache-maven-3.3.9
- path:在系統(tǒng)變量中,找到path上遥,添加上去
;%M2_HOME%\bin;
- 重新打開 Windows 命令行搏屑,輸入
mvn -version
Microsoft Windows [Version 10.0.14393] (c) 2016 Microsoft Corporation. All rights reserved. C:\Users\xxx>mvn -version Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T00:41:47+08:00) Maven home: C:\Apache\apache-maven-3.3.9 Java version: 1.8.0_66, vendor: Oracle Corporation Java home: C:\Program Files\Java\jdk1.8.0_66\jre Default locale: en_US, platform encoding: GBK OS name: "windows 10", version: "10.0", arch: "amd64", family: "dos"
?
- %M2_HOME%:在系統(tǒng)變量添加角虫,路徑為安裝的 Maven 的根目錄沾谓,例如
-
-
建立一個Maven項目
使用 IDEA 新建 Maven Project,并添加依賴如下:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
在彈出的浮層中點擊“Enable Auto-import”即可粉楚。
然后在 src/main/test/java 文件夾下面可以新建 Java Class 進行測試類的編寫。
將被測試的類 放在 src/main/java 的文件夾下亮垫。
?
-
使用Maven生成JUnit報告
Maven 本身并不是一個單元測試框架模软,能做的只是在構(gòu)建執(zhí)行到特定生命周期階段的時間,通過插件來執(zhí)行 JUnit 的測試用例饮潦。這個插件就是 maven-surefire-plugin燃异,可以稱之為測試運行器。
默認情況下继蜡,maven-surefire-plugin 的 test 目標會自動執(zhí)行測試用例源碼路徑(默認為 src/main/test/java/)下所有符合一組命名模式的測試類回俐。這組模式為:
模式 描述 **/Test*.java
任何子目錄下所有命名以 Test 開頭的 Java 類 **/*Test.java
任何子目錄下所有命名以 Test 結(jié)尾的 Java 類 **/*TestCase.java
任何子目錄下所有命名以 TestCase 結(jié)尾的 Java 類 按照上述描述的模式,添加以下依賴:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.19.1</version> <configuration> <skipTests>false</skipTests> <source>1.8</source> <target>1.8</target> <includes> <include>**/*Tests.java</include> <include>**/*TestCase.java</include> </includes> </configuration> </plugin>
然后在需要運行的目錄中稀并,執(zhí)行
mvn test
仅颇,便可完成測試,并生成報告碘举。默認情況下忘瓦,maven-surefire-plugin 會在項目的 target/surefire-reports 目錄下生成兩種格式的錯誤報告:- 簡單文本格式
- 與 JUnit 兼容的 XML 格式
這樣的報告對于獲得信息足夠了,XML 格式的測試報告主要是為了支持工具的解析引颈,是 Java 單元測試報告的事實標準耕皮。
3.3 單元測試框架在自動化測試中的應(yīng)用
-
自動化測試的介紹
當前,軟件測試貫穿到整個軟件開發(fā)生命周期的全過程中蝙场,不再停留在編程之后的某個階段凌停,尤其是敏捷開發(fā)開始廣泛的應(yīng)用于互聯(lián)網(wǎng)行業(yè)以后,敏捷測試就把軟件測試解釋為
對軟件產(chǎn)品質(zhì)量的持續(xù)評估
售滤。在敏捷方法中罚拟,持續(xù)測試被提倡。當前的持續(xù)測試的實施趴泌,主要依托于持續(xù)集成舟舒。自動化測試:以人為驅(qū)動的測試行為轉(zhuǎn)化為機器執(zhí)行的一種過程
這里我們使用 Selenium 工具進行自動化測試的應(yīng)用。
Selenium is a suite oftools to automate web browsers across many platforms.
selenium 硒嗜憔,
/s?'lini?m/
Selenium是開源的自動化測試工具秃励,它主要是用于Web 應(yīng)用程序的自動化測試,不只局限于此吉捶,同時支持所有基于web 的管理任務(wù)自動化夺鲜。
Selenium 是用于測試 Web 應(yīng)用程序用戶界面 (UI) 的常用框架皆尔。它是一款用于運行端到端功能測試的超強工具。您可以使用多個編程語言編寫測試币励,并且 Selenium 能夠在一個或多個瀏覽器中執(zhí)行這些測試慷蠕。
-
使用 JUnit + Selenium 進行自動化測試
接下來我們使用 Junit + Selenium 構(gòu)建自動化測試
步驟如下:
安裝 Java 和 IDEA
-
使用 IDEA 創(chuàng)建 Maven Project,并使用如下 pom.xml 文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-parent</artifactId> <version>2.53.1</version> </parent> <artifactId>selenium-server</artifactId> <name>selenium-server</name> <dependencies> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-remote-driver</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-exec</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-csv --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-csv</artifactId> <version>1.4</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.3</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.19.1</version> <configuration> <skipTests>false</skipTests> <includes> <include>**/*Tests.java</include> </includes> </configuration> </plugin> </plugins> </build> </project>
?
-
在 src/test/java 下創(chuàng)建 Java Class 進行編寫自動化測試腳本食呻。腳本如下:
public class RanzhiTestCase{ // 聲明成員變量 private WebDriver driver; private String baseUrl; @Before public void setUp(){ this.driver = new FirefoxDriver(); this.baseUrl = "http://localhost:808/ranzhi/www"; @After public void tearDown(){ this.driver.quit(); } @Test public void testLogIn() { // 聲明局部變量流炕,傳遞全局的driver給它進行操作 WebDriver driver = this.driver; // 步驟1 // 用局部變量driver 打開然之的登錄地址 driver.get(baseUrl); // 讓java代碼停止運行1秒鐘,等待瀏覽器進一步響應(yīng) try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 斷言:檢查是否打開了正確的登錄地址 Assert.assertEquals("登錄頁面打開錯誤", this.baseUrl + "/sys/user-login-L3JhbnpoaS93d3cvc3lzLw==.html", driver.getCurrentUrl()); // 步驟2 // 輸入用戶名 密碼 進行登錄 // 輸入用戶名 WebElement accountElement = driver.findElement(By.id("account")); accountElement.clear(); accountElement.sendKeys("admin"); // 輸入密碼 WebElement passwordElement = driver.findElement(By.id("password")); passwordElement.clear(); passwordElement.sendKeys("123456"); // 點擊登錄按鈕 driver.findElement(By.id("submit")).click(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Assert.assertEquals("登錄頁面登錄跳轉(zhuǎn)失敗", this.baseUrl + "/sys/index.html", driver.getCurrentUrl()); } }
-
Selenium 推薦的 Page Object 設(shè)計模式進行方案設(shè)計
自動化測試方案(高階版).png
3.4 使用 Jenkins 進行持續(xù)質(zhì)量審查
-
什么持續(xù)集成
持續(xù)集成仅胞,Continuous integration 每辟,簡稱CI。
隨著軟件開發(fā)復(fù)雜度的不斷提高干旧,團隊開發(fā)成員間如何更好地協(xié)同工作以確保軟件開發(fā)的質(zhì)量已經(jīng)慢慢成為開發(fā)過程中不可回避的問題渠欺。尤其是近些年來,敏捷(Agile) 在軟件工程領(lǐng)域越來越紅火椎眯,如何能再不斷變化的需求中快速適應(yīng)和保證軟件的質(zhì)量也顯得尤其的重要挠将。
持續(xù)集成正是針對這一類問題的一種軟件開發(fā)實踐。首先我們看一下编整,敏捷教父
Martin Fowler
對持續(xù)集成的定義:Martin Fowler:*Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly. *
具體定義:持續(xù)集成式一種軟件開發(fā)實踐舔稀。它倡導(dǎo)團隊的成員必須經(jīng)常的集成它們的工作,通常至少每天一次甚至更多次集成闹击。每次集成都需要通過自動化的構(gòu)建(包括編譯代碼镶蹋、構(gòu)建應(yīng)用、部署程序以及自動化測試)來驗證赏半,從而盡早盡快的發(fā)現(xiàn)集成中的錯誤贺归。大量的團隊利用這樣的方式來更快的開發(fā)內(nèi)聚的軟件。大大減少此過程中的集成問題断箫。
具體的流程圖如下:
img持續(xù)集成強調(diào)開發(fā)人員提交了新代碼之后拂酣,立刻進行構(gòu)建、(單元仲义、自動化)測試婶熬。根據(jù)測試結(jié)果,我們可以確定新代碼和原有代碼能否正確地集成在一起埃撵。
首先赵颅,解釋下集成。我們所有項目的代碼都是托管在SVN服務(wù)器上暂刘。每個項目都要有若干個單元測試饺谬,并有一個所謂集成測試。所謂集成測試就是把所有的單元測試跑一遍以及其它一些能自動完成的測試谣拣。只有在本地電腦上通過了集成測試的代碼才能上傳到SVN服務(wù)器上募寨,保證上傳的代碼沒有問題族展。所以,集成指集成測試拔鹰。
再說持續(xù)仪缸。不言而喻,就是指長期的對項目代碼進行集成測試列肢。既然是長期恰画,那肯定是自動執(zhí)行的,否則例书,人工執(zhí)行則沒有保證锣尉,而且耗人力。對此决采,我們有一臺服務(wù)器,它會定期的從SVN中檢出代碼坟奥,并編譯树瞭,然后跑集成測試。每次集成測試結(jié)果都會記錄在案爱谁。完成這方面工作的就是下面要介紹的Jenkins軟件晒喷。當然,它的功能遠不止這些访敌。在我們的項目中凉敲,執(zhí)行這個工作的周期是1天。也就是寺旺,服務(wù)器每1天都會準時地對SVN服務(wù)器上的最新代碼自動進行一次集成測試爷抓。
img
-
Jenkins環(huán)境搭建
Jenkins,原名Hudson阻塑,2011年改為現(xiàn)在的名字蓝撇,它 是一個開源的實現(xiàn)持續(xù)集成的軟件工具。官方網(wǎng)站:http://jenkins-ci.org/陈莽。
Hudson是在2004年的夏天由Sun公司開發(fā)的(就是開發(fā)Java的那家)渤昌,2005年2月開源并發(fā)布了第一個版本。Hudson發(fā)布的時候CruiseControl是CI界的老大哥走搁,但是很快独柑,在大約2007年的時候Hudson已經(jīng)超越CruiseControl。2008年5月的JavaOne大會上私植,Hudson獲得了開發(fā)解決方案類的Duke's Choice獎項忌栅。從此,小弟翻身做大哥兵琳,Hudson成為CI的代名詞狂秘。
2009年6月骇径,Oracle收購Sun。2010年9月者春,Oracle注冊了Hudson的商標破衔,然后就沒有然后了。原Hudson的成員創(chuàng)建了Jenkins钱烟。
Jenkins 能實施監(jiān)控集成中存在的錯誤晰筛,提供詳細的日志文件和提醒功能,還能用圖表的形式形象地展示項目構(gòu)建的趨勢和穩(wěn)定性拴袭。
需要從官網(wǎng)下載Jenkins的文件读第,在本地安裝Java(jdk)的環(huán)境以后,直接執(zhí)行以下語句進行安裝:
java -jar jenkins.war
隨后訪問http://localhost:8080即可
最后拥刻,將Jenkins安裝成Windows服務(wù)啟動怜瞒。
在Jenkins的主頁中選擇 Manager Jenkins
[圖片上傳失敗...(image-b12cb3-1516466328793)]
接下來選擇 Install as Windows Service
[圖片上傳失敗...(image-9e447f-1516466328793)]
在Installation Directory中選擇jenkin的安裝路徑。這里會默認產(chǎn)生般哼,直接點擊Install就可以了吴汪。
隨后我們點擊Yes,然后可以看到Windows服務(wù)中添加了Jenkins的服務(wù)蒸眠,并已經(jīng)設(shè)置為自動和啟動狀態(tài)漾橙。
-
部署Jenkins與運行
-
創(chuàng)建Jenkins Job
Jenkins提供了四種類型的Job:
- 構(gòu)建一個自由風(fēng)格的軟件項目:這個是Jenkins的主要功能,可以構(gòu)建一個你自己需要的項目楞卡。
- 構(gòu)建一個maven項目:這是基于maven構(gòu)建的項目霜运,整個過程將會基于你的.pom文件進行構(gòu)建,大大減輕構(gòu)建的配置
- 構(gòu)建一個多配置項目:這種項目適用多配置的項目蒋腮,比如多個平臺定制的構(gòu)建淘捡,多個測試環(huán)境的部署構(gòu)建等。
- 監(jiān)控一個外部的任務(wù):這種事允許你記錄和執(zhí)行不在Jenkins中的Job徽惋,這些Job可以運行在遠程的主機上案淋,Jenkins通過遠程自動構(gòu)建,作為一個控制面板而存在险绘。
-
運行Jenkins Job
運行Job只需要在頁面的左側(cè)選中已經(jīng)列出的項目踢京,進行操作就可以了。選擇立即構(gòu)建宦棺,便可以進行自動構(gòu)建的工作了瓣距。
-
定時構(gòu)建 Job
目前有一個每日構(gòu)建的概念。
Daily Build代咸,每日構(gòu)建蹈丸。需要Jenkins在每日固定的時間進行代碼自動構(gòu)建、集成和測試的工作。那么需要定制執(zhí)行時間逻杖。Jenkins的自動構(gòu)建定制時間是遵循cron語法的奋岁。具體來說,每一行包括了5個用白空格或者Tab隔開的字段荸百,分別是:
MINUTE HOUR DOM MONTH DOW
闻伶。具體的格式我們參考下圖字段 說明 示例 MINUTE Minutes within the hour (0–59) 30 HOUR The hour of the day (0–23) 17 DOM The day of the month (1–31) 1 MONTH The month (1–12) 5 DOW The day of the week (0–7) where 0 and 7 are Sunday. 5 然后每個格式,都可以由
*
够话,-
蓝翰,/
和,
4種字符組成:-
*
代表所有可能的值 -
-
代表整數(shù)之間的范圍 -
/
代表指定的時間的間隔頻率 -
,
代表指定的列表范圍
命令的格式參考和示例: 注意時間是倫敦時間
分鐘 小時 天 月份 星期 命令格式 描述 H 16 1,10,20 * * H 16 1,10,20 * *
每個月的1,10女嘲,20日的16:00執(zhí)行 H 16 * * 1-5 H 16 * * 1-5
每個周的周一到周五的16:00執(zhí)行 30 17 * * 1畜份,5 30 17 * * 1,5
每個周的周一和周五的17:30執(zhí)行 -
-
Jenkins Job 示例
## 1. 創(chuàng)建SVN倉庫 ## https://172.31.95.168/svn/DemoRepo/ ## ciuser / ciuser ## 2. 從SVN倉庫簽出文件到CI Server ## 3. 構(gòu)建 build ## 4. 部署 deploy ## 4.1 備份目標文件夾 ## 若有ranzhi_bak 需要先刪除 rd /s /q c:\xampp\htdocs\ranzhi_bak ## 把 htdoc的ranzhi改成 ranzhi_bak xcopy c:\xampp\htdocs\ranzhi c:\xampp\htdocs\ranzhi_bak\ /s /e /y rd /s /q c:\xampp\htdocs\ranzhi ## 4.2 復(fù)制構(gòu)建的版本到目標文件夾 ## 把workspace的 ranzhi 復(fù)制到 htdocs下面 xcopy "%WORKSPACE%\ranzhi" c:\xampp\htdocs\ranzhi\ /s /e /y ## 4.3 恢復(fù)配置文件 ## 復(fù)制 ranzhi_bak\config\my.php 到 ranzhi\config\my.php xcopy c:\xampp\htdocs\ranzhi_bak\config\my.php c:\xampp\htdocs\ranzhi\config\ /e ## 5. 自動化測試 python D:\Git\Coding\BWFTraining\3.03_Selenium\codes\weekend2demo\ranzhi_test_runner.py
?
-