jbehave_使用JBehave,Gradle和Jenkins的行为驱动开发(BDD)
jbehave
行為驅(qū)動開發(fā) (BDD)是一個協(xié)作過程 ,產(chǎn)品所有者,開發(fā)人員和測試人員可以合作交付可為業(yè)務(wù)帶來價值的軟件。 BDD是 測試驅(qū)動開發(fā) (TDD) 的合理下一步 。
行為驅(qū)動的發(fā)展
本質(zhì)上,BDD是一種交付需求的方法。 但不僅有任何要求,還包括可執(zhí)行要求! 使用BDD,您可以以可以針對該軟件運(yùn)行的格式來編寫方案 ,以確定該軟件是否按預(yù)期運(yùn)行。
情境
場景以“ 給定,何時,然后”格式(也稱為Gherkin)編寫:
Given the ATM has $250 And my balance is $200 When I withdraw $150 Then the ATM has $100 And my balance is $50Give表示初始上下文, When表示發(fā)生了有趣的事件, 然后斷言了預(yù)期的結(jié)果。 并且可以用來代替重復(fù)的關(guān)鍵字,以使方案更具可讀性。
Give / When / Then是一個非常強(qiáng)大的習(xí)慣用法 ,幾乎可以描述任何要求。 這種格式的場景也很容易解析,因此我們可以自動運(yùn)行它們。
BDD場景對開發(fā)人員非常有用,因?yàn)樗鼈兲峁┝擞嘘P(guān)故事是否完成的快速而明確的反饋。 不僅可以提供主要成功方案,還可以提供替代方案和異常方案 ,如濫用案例 。 后者要求產(chǎn)品負(fù)責(zé)人不僅要與測試人員和開發(fā)人員合作,還要與安全專家合作。 結(jié)果是, 管理安全要求變得更加容易。
盡管BDD實(shí)際上是關(guān)于協(xié)作過程的,而不是關(guān)于工具的,但在本文的其余部分中,我將專注于工具。 請記住, 工具永遠(yuǎn)無法挽救您,而溝通和協(xié)作則可以 。 消除了這一警告,讓我們開始使用一些開源工具來實(shí)現(xiàn)BDD。
杰貝夫
JBehave是Java的BDD工具。 它從故事文件中解析場景,將它們映射到Java代碼,通過JUnit測試運(yùn)行它們,并生成報(bào)告。
JUnit的
這是我們使用JUnit運(yùn)行故事的方式:
@RunWith(AnnotatedEmbedderRunner.class) @UsingEmbedder(embedder = Embedder.class, generateViewAfterStories = true,ignoreFailureInStories = true, ignoreFailureInView = false, verboseFailures = true) @UsingSteps(instances = { NgisRestSteps.class }) public class StoriesTest extends JUnitStories {@Overrideprotected List<String> storyPaths() {return new StoryFinder().findPaths(CodeLocations.codeLocationFromClass(getClass()).getFile(),Arrays.asList(getStoryFilter(storyPaths)), null);}private String getStoryFilter(String storyPaths) {if (storyPaths == null) {return '*.story';}if (storyPaths.endsWith('.story')) {return storyPaths;}return storyPaths + '.story';}private List<String> specifiedStoryPaths(String storyPaths) {List<String> result = new ArrayList<String>();URI cwd = new File('src/test/resources').toURI();for (String storyPath : storyPaths.split(File.pathSeparator)) {File storyFile = new File(storyPath);if (!storyFile.exists()) {throw new IllegalArgumentException('Story file not found: ' + storyPath);}result.add(cwd.relativize(storyFile.toURI()).toString());}return result;}@Overridepublic Configuration configuration() {return super.configuration().useStoryReporterBuilder(new StoryReporterBuilder().withFormats(Format.XML, Format.STATS, Format.CONSOLE).withRelativeDirectory('../build/jbehave')).usePendingStepStrategy(new FailingUponPendingStep()).useFailureStrategy(new SilentlyAbsorbingFailure());}}這使用JUnit 4的@RunWith注釋來指示將運(yùn)行測試的類。 AnnotatedEmbedderRunner是JBehave提供的JUnit Runner 。 它尋找@UsingEmbedder批注以確定如何運(yùn)行故事:
- generateViewAfterStories指示JBehave在運(yùn)行故事后創(chuàng)建測試報(bào)告
- 當(dāng)故事失敗時, ignoreFailureInStories防止JBehave引發(fā)異常。 這對于與Jenkins集成至關(guān)重要,如下所示
@UsingSteps批注將方案中的步驟鏈接到Java代碼。 下面的更多內(nèi)容。 您可以列出多個類別。
我們的測試類重新使用了JBehave的JUnitStories類,這使得運(yùn)行多個故事變得容易。 我們只需要實(shí)現(xiàn)兩種方法: storyPaths()和configuration() 。
storyPaths()方法告訴JBehave在哪里找到要運(yùn)行的故事。 我們的版本有點(diǎn)復(fù)雜,因?yàn)槲覀兿M軌驈奈覀兊腎DE和命令行中運(yùn)行測試,并且因?yàn)槲覀兿M軌蜻\(yùn)行所有故事或特定子集。
我們使用系統(tǒng)屬性bdd.stories指示要運(yùn)行的故事。 這包括對通配符的支持。 我們的命名約定要求故事文件名以角色開頭,因此我們可以使用-Dbdd.stories=wanda_*類的-Dbdd.stories=wanda_*輕松運(yùn)行單個角色的所有故事。
configuration()方法告訴JBehave 如何運(yùn)行故事并對其進(jìn)行報(bào)告 。 我們需要XML輸出,以便在Jenkins中進(jìn)行進(jìn)一步處理,如下所示。
感興趣的一件事是報(bào)告的位置。 JBehave支持Maven,這很好,但是他們假設(shè)每個人都遵循Maven約定,但事實(shí)并非如此。 默認(rèn)情況下,輸出進(jìn)入一個名為target的目錄,但是我們可以通過指定相對于target目錄的路徑來覆蓋該目錄。 我們使用Gradle代替Maven,并且Gradle的臨時文件進(jìn)入build目錄,而不是target 。 更多關(guān)于Gradle的信息。
腳步
現(xiàn)在我們可以運(yùn)行我們的故事,但是它們會失敗。 我們需要告訴JBehave如何將場景中的Given / When / Then步驟映射到Java代碼。 步驟類確定可以在方案中使用的詞匯表。 因此,他們定義了一種用于接受測試我們的應(yīng)用程序的領(lǐng)域特定語言 (DSL)。
我們的應(yīng)用程序具有RESTful接口,因此我們編寫了通用的REST DSL。 但是,由于REST中的HATEOAS約束,客戶端需要大量調(diào)用才能發(fā)現(xiàn)其應(yīng)使用的URI。 這樣寫場景變得很無聊和重復(fù),因此我們在REST DSL之上添加了特定于應(yīng)用程序的DSL。 這使我們可以用產(chǎn)品負(fù)責(zé)人理解的術(shù)語來編寫方案 。
在通用REST步驟之上分層特定于應(yīng)用程序的步驟具有一些優(yōu)點(diǎn):
- 實(shí)施新的特定于應(yīng)用程序的DSL很容易,因?yàn)樗鼈冎恍枰{(diào)用REST特定的DSL
- REST專用的DSL可以與其他項(xiàng)目共享
Gradle
有了步驟,我們可以從我們最喜歡的IDE中運(yùn)行我們的故事。 這對開發(fā)人員來說效果很好,但是不能用于持續(xù)集成 (CI)。
我們的CI服務(wù)器運(yùn)行的是無頭構(gòu)建,因此我們需要能夠從命令行運(yùn)行BDD方案。 我們使用Gradle使構(gòu)建自動化,并且Gradle已經(jīng)可以運(yùn)行JUnit測試。 但是,我們的構(gòu)建是一個多項(xiàng)目構(gòu)建。 在構(gòu)建所有項(xiàng)目,創(chuàng)建發(fā)行版并啟動應(yīng)用程序之前,我們不希望運(yùn)行BDD方案。
因此,首先,我們在包含BDD故事的項(xiàng)目上禁用運(yùn)行測試:
test {onlyIf { false } // We need a running server }接下來,我們創(chuàng)建另一個可以在啟動應(yīng)用程序后運(yùn)行的任務(wù):
task acceptStories(type: Test) {ignoreFailures = truedoFirst {// Need 'target' directory on *nix systems to get any outputfile('target').mkdirs()def filter = System.getProperty('bdd.stories') if (filter == null) {filter = '*'}def stories = sourceSets.test.resources.matching { it.include filter}.asPathsystemProperty('bdd.stories', stories)} }在這里,我們看到了Gradle的力量。 我們定義了一個Test類型的新任務(wù),以便它已經(jīng)可以運(yùn)行JUnit測試。 接下來,我們使用一些Groovy腳本配置該任務(wù)。
首先,我們必須確保target目錄存在。 我們不需要甚至不需要它,但是如果沒有它,JBehave將無法在* nix系統(tǒng)上正常工作。 我想那是一點(diǎn)Maven主義
接下來,再次使用bdd.stories系統(tǒng)屬性添加對運(yùn)行故事子集的支持。 我們的故事文件位于src/test/resources ,因此我們可以使用標(biāo)準(zhǔn)Gradle test 源集輕松訪問它們。 然后,我們?yōu)檫\(yùn)行測試的JVM設(shè)置系統(tǒng)屬性bdd.stories 。
詹金斯
現(xiàn)在,我們可以從IDE和命令行運(yùn)行BDD方案。 下一步是將它們集成到我們的CI版本中。
我們可以將JBehave報(bào)告存檔為工件,但是,老實(shí)說,JBehave生成的報(bào)告并不是很好。 幸運(yùn)的是,JBehave團(tuán)隊(duì)還維護(hù)了Jenkins CI服務(wù)器的插件 。 該插件需要事先安裝xUnit插件 。
將xUnit和JBehave插件安裝到j(luò)enkins中之后,我們可以配置Jenkins作業(yè)以使用JBehave插件。 首先,添加xUnit生成后操作。 然后,選擇JBehave測試報(bào)告。
使用此配置,在我們的BDD故事上運(yùn)行JBehave的輸出看起來像常規(guī)單元測試的輸出:
請注意,圖中的黃色部分表示待處理的步驟。 這些用于BDD場景,但在Java Steps類中沒有對應(yīng)的對象。 未完成的步驟顯示在測試結(jié)果的“ Skip列中:
請注意,JBehave Jenkins插件如何將故事轉(zhuǎn)換為測試,將場景轉(zhuǎn)換為測試方法。 這樣可以很容易地發(fā)現(xiàn)哪些方案需要更多工作。
盡管JBehave插件運(yùn)行良好,但是有兩點(diǎn)可以改進(jìn):
- 測試的輸出未顯示。 這使得很難弄清楚場景失敗的原因。 因此,我們還存檔了JUnit測試報(bào)告
- 如果將ignoreFailureInStories配置為false ,則JBehave會在失敗時引發(fā)異常,該異常會截?cái)郮ML輸出。 然后,JBehave Jenkins插件將無法再解析XML(因?yàn)樗母袷讲徽_),并且會完全失敗,從而使您沒有測試結(jié)果
所有這些都是不便之處,我們對自動化的BDD方案感到非常滿意。
祝您編程愉快,別忘了分享!
參考: 安全軟件開發(fā)博客上來自JCG合作伙伴 Remon Sinnema的JBehave,Gradle和Jenkins的行為驅(qū)動開發(fā)(BDD) 。
翻譯自: https://www.javacodegeeks.com/2012/09/behavior-driven-development-bdd-with.html
jbehave
總結(jié)
以上是生活随笔為你收集整理的jbehave_使用JBehave,Gradle和Jenkins的行为驱动开发(BDD)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 班集体形成的标志是什么 班集体形成的标志
- 下一篇: 使用Java第2部分查询DynamoDB