Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
ÐÐΪÇý¶¯¿ª·¢£¨BDD£©Äã×¼±¸ºÃÁËÂð£¿
 
  4325  次浏览      27
 2019-3-27
 
±à¼­ÍƼö:

±¾ÎÄÀ´×ÔÓÚcsdn£¬±¾ÎÄÖ÷Ҫͨ¹ýÐÐΪÇý¶¯¿ª·¢BDDµÄÀý×Ó˵Ã÷ΪʲôʹÓÃÐÐΪÇý¶¯¿ª·¢£¬ÓÃʲô¿ò¼ÜÀ´×öÐÐΪÇý¶¯¿ª·¢£¬ÐÐΪÇý¶¯¿ª·¢µÄºËÐÄÔ­Àí£¬Ï£Íû¶ÔÄúµÄѧϰÓÐËù°ïÖú¡£

¸ù¾ÝBDD in actionÒ»ÊéµÄ½éÉÜ£¬

Behavior-Driven Development (BDD) is a set of software engineering practices

designed to help teams build and deliver more valuable, higher quality software faster.

It draws on Agile and lean practices including, in particular, Test-Driven Development

(TDD) and Domain-Driven Design (DDD). But most importantly, BDD provides a common language based on simple, structured sentences expressed in English (or in the native language of the stakeholders) that facilitate communication between project team members and business stakeholders.

·­Òë³ÉÖÐÎĵĴó¸ÅÒâ˼¾ÍÊÇ£¬ÐÐΪÇý¶¯¿ª·¢ÊÇÒ»¸öÈí¼þ¹¤³ÌµÄϵÁÐʵ¼ù£¬Äܹ»°ïÖúÍŶӿìËÙ¹¹½¨ºÍ½»¸¶¸ü¶à¼ÛÖµºÍÖÊÁ¿µÄÈí¼þ²úÆ·¡£ÆäºÍÃô½ÝÒѾ­¾«ÒæµÄ¿ª·¢Êµ¼ù£¬ÊÇÒ»ÂöÏà³ÐµÄ£¬ÌرðÊDzâÊÔÇý¶¯¿ª·¢£¬ÒѾ­ÁìÓòÇý¶¯¿ª·¢¡£µ«ÊÇ×îÖØÒªµÄÊÇBDDÌṩÁËÒ»ÖÖͨÓõ쬼òµ¥µÄ£¬½á¹¹»¯µÄÃèÊöÓïÑÔ£¬ÕâÖÖÓïÑԼȿÉÒÔÊÇÓ¢ÓïÒ²¿ÉÒÔÊÇÆäËû±¾µØµÄÓïÑÔ£¬Í¨¹ýËûÄܹ»ºÜ·½±ãÈÃÏîÄ¿³ÉÔ±ºÍÒµÎñ¸ÉϵÈ˷dz£Ë³³©µÄ¹µÍ¨ÐèÇ󣬼°Ê±ÕâЩ¸ÉϵÈ˲»¶®µÄÈκαà³ÌÓïÑÔ¡£ÏÂÃæ¾ÍÊÇÒ»¸öÀý×Ó¡£

ÊDz»ÊǺܺöÁ¶®£¬ÉÏÃæÆäʵ¾Í½ÐFeature£¨ÌØÐÔÎļþ£©£¬Æä×ñÑ­µÄGherkin±ê×¼£¬ÆäÓÐÏÂÃæµÄ¹Ø¼ü×Ö£¬ºÜºÃÀí½â£¬

1.Feature

2.Background

3.Scenario

4.Given

5.When

6.Then

7.And

8.But

9.*

10.Scenario Outline

11.Examples

ÕâÖÖÌØÐÔÎļþ£¬¿Í»§£¬ÏîÄ¿¾­Àí£¬BA£¬QA¶¼ÄÜ¿´¶®£¬ÒòΪÆä¾ÍÊÇÒ»¸ö¹Êʵã»òÕßÐèÇóµã£¬¶øÇÒͨ¹ýÌØ¶¨µÄ¹¤¾ß£¬±ÈÈçcucumberµÄ¹¤¾ß£¬Äܹ»°ÑÆä×Ô¶¯×ª»»³ÉΪ´úÂë¡£¿ª·¢ÈËÔ±¸ù¾Ý×Ô¶¯Éú³ÉµÄ´úÂ룬¶ÏÑÔһЩԤÆÚµÄÐÐΪ£¬²¢¸ù¾ÝÕâЩÐÐΪ£¬Íê³ÉÏàÓ¦µÄ´úÂëʵÏÖ£¬ÔÚ´úÂëʵÏֵĻù´¡ÉÏ£¬½øÐÐÖØ¹¹£» ÕâÑù¾ÍΪһ¸öÏîÄ¿Öеĸ÷¸öÈËÔ±Á˽âÏîÄ¿µÄÐèÇó£¬ÊµÏÖÌṩÁËÒ»¸öºÜºÃµÄ½»»¥ÇÅÁº¡£ÏÂÃæÊÇÆäÒ»¸ö½»»¥µÄ¹ý³Ì¡£

Èç¹ûÊÇ´«Í³µÄ·½Ê½£¬Æä½»»¥·½Ê½£¬Ó¦¸ÃÊÇ£¬

ͨ¹ý¶Ô±È£¬´ó¼ÒÊDz»ÊÇ·¢ÏÖBDDµÄÕâÖÖ·½Ê½£¬°ÑÓû§»òÕ߿ͻ§ÕæÕýµÄͨ¹ýFeatureÎļþÁªÏµÔÚÒ»ÆðÁË£¬Æä¹µÍ¨ÊÇ˳³©µÄ£¬QA£¬BA£¬¿ª·¢£¬²âÊÔ£¬¿Í»§£¬Óû§¿ÉÒÔͨ¹ýÕâһý½é£¬½øÐиßЧÎÞÕϰ­µÄ¹µÍ¨£¬¶ø²»ÊÇÏñ´«Í³µÄ·½Ê½£¬Í¨¹ýBA½øÐжþ´Îת´ï£¬´Ó¶ø¶ªÊ§Á˺ܶàÖØÒªµÄÐèÇó¡£

Óɴ˿ɼû£¬ÆäBDDµÄºÃ´¦ÈçÏ£º

¼õÉÙÀË·Ñ

½ÚÊ¡³É±¾

ÈÝÒײ¢ÇÒ°²È«µÄÊÊÓ¦±ä»¯

ÒòΪÉÙÁËÖмäµÄת´ï»·½Ú£¬´Ó¶øÄܹ»¿ìËÙ½»¸¶²úÆ·

ÏÂÃæ¿´Ò»¸ö¼òµ¥µÄÀý×Ó

´ÓÉÏͼ¿ÉÒÔ¿´³ö£¬µ±Ò»¸öÐèÇó¹ýÀ´µÄʱºò£¬ÏÈͨ¹ýÏîÄ¿¸ÉϵÈ˶¼ÄÜÀí½âµÄFeatureÎļþ£¬ÃèÊöÏîÄ¿µÄUser Story£¬ ÓеÄÀïÃæ»¹ÓÐÏêϸÉú¶¯µÄÊý¾Ý·¶Àý£¨example£©£¬´Ó¶øÄܹ»ÈÃËùÓеÄÈ˸ü¼ÓÈÝÒ×Àí½âÆäÐèÇó£¬ ±ÈÈç

ͨ¹ýÉÏÃæµÄÊý¾Ý·¶Àý£¨example£©µÄ±í¸ñÊDz»ÊǸü¼ÓÈÝÒ×µÄÀí½âµ±Ç°caseµÄÒâͼÁË¡£µ±FeatureºÍExampleÎļþ¶¼Íê³Éºó£¬½èÖúÓÚµÚÈý·½µÄ¿ªÔ´¿ò¼ÜʵÏÖ£¬±ÈÈçCucumber£¬jBehave£¬SpecFlowµÈ°ÑFeatureºÍExample×°»»³É´úÂ룬Ȼºóͨ¹ýµÚ²ã´ÎµÄµ¥Ôª²âÊÔ¿ò¼Ü£¬±ÈÈçJUnit£¬NUnit£¬Spock£¬RSpec£¬½áºÏ²âÊÔÇý¶¯¿ª·¢£¬´Ó¶ø°ÑÒµÎñ´úÂëµÄÂß¼­ÊµÏÖ¡£ÕæÊÇÒ»¾Ù¶àµÃ¡£

±ÊÕß¾ÍÒÔCucumberºÍJUnitΪÀý£¬¾ÙÒ»¸öBDDµÄÀý×Ó°É¡£´ó¼Ò¶ÔJUnit±È½ÏÊìϤ£¬µ«ÊǶÔCucumber¿ÉÄÜ»áÏà¶ÔİÉúÒ»µã£¬±ÊÕ߾ͻ¨Ò»µã±ÊÄ«£¬¼òµ¥½éÉÜÁËÒ»ÏÂCucumber¡£CucumerÊÇÒ»¸öʵÏÖÁËBDDµÄÒ»¸ö¿ò¼Ü£¬ÆäÖ§³ÖÏÂÃæµÄÓïÑԺͿò¼Ü¼¯³É£¬

ÊDz»ÊǸоõºÜÇ¿´ó°¡£¡£¡£¡£¡ ÏÂÃæ½øÈëʵս£¬

1. Maven¿âµÄÒÀÀµ

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>uk.co.claysnow</groupId>
<version>1.0</version>
<packaging>jar</packaging>
<name>Cucumber-JVM Book ATM Example</name>
<artifactId>atm-example</artifactId>
<properties>
<cucumber.version>1.2.0</cucumber.version>
<junit.version>4.11</junit.version>
<picocontainer.version>2.14.2</picocontainer.version>
</properties>
<dependencies>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer</artifactId>
<version>${picocontainer.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.2</version>
<configuration>
<argLine>-Duser.language=en</argLine>
<argLine>-Xmx1024m</argLine>
<argLine>-XX:MaxPermSize=256m</argLine>
<argLine>-Dfile.encoding=UTF-8</argLine>
<useFile>false</useFile>
</configuration>
</plugin>
</plugins>
</build>
</project>

2. °²×°Cucumber Eclipse²å¼þ

ΪÁËÖ§³ÖFeatureµÄGherkinÓï·¨£¬ÎÒÃÇÐèÒªÔÚEclipse°²×°ÏÂÃæµÄ²å¼þ£º

https://cucumber.io/cucumber-eclipse/update-site

¾ßÌå°²×°·½·¨£¬Çëµ½°Ù¶È»òÕßgoogleËÑË÷¡£ÏÂÃæ¿´Ò»¸ö¾ßÌåµÄÀý×Ó£º

3. FeatureÎļþ

Feature: Cash Withdrawal
Scenario: Successful withdrawal from an account in credit
Given I have deposited $100.00 in my account
When I withdraw $20
Then $20 should be dispensed

4. Éú³ÉµÄJava SpecificationÎļþ

import cucumber.api.java.en.*;
import cucumber.api.Transform;
import org.junit.*;
import support.KnowsTheDomain;
import transforms.MoneyConverter;
public class AccountSteps {
KnowsTheDomain helper;
public AccountSteps(KnowsTheDomain helper) {
this.helper = helper;
}
@Given("^I have deposited (\\$\\d+\\.\\d+) in my account$")
public void iHaveDeposited$InMyAccount(@Transform(MoneyConverter.class) Money amount)
throws Throwable {
helper.getMyAccount().deposit(amount);
Assert.assertEquals("Incorrect account balance -", amount, helper.getMyAccount().getBalance());
}
}

mport cucumber.api.java.en.*;
import org.junit.*;
import support.KnowsTheDomain;
import transforms.MoneyConverter;
public class CashSlotSteps {
KnowsTheDomain helper;
public CashSlotSteps(KnowsTheDomain helper) {
this.helper = helper;
}
@Given("^\\$(\\d+) should be dispensed$")
public void $ShouldBeDispensed(int dollars) throws Throwable {
Assert.assertEquals("Incorrect amount dispensed -", dollars,
helper.getCashSlot().getContents());
}
}

import cucumber.api.java.en.*;
import support.KnowsTheDomain;
public class TellerSteps {
KnowsTheDomain helper;
public TellerSteps(KnowsTheDomain helper) {
this.helper = helper;
}
@When("^I withdraw \\$(\\d+)$")
public void iWithdraw$(int amount) throws Throwable {
helper.getTeller().withdrawFrom(helper.getMyAccount(), amount);
}
}

5. Cucumber ²âÊÔµÄÔËÐÐÈë¿Ú

import cucumber.api.junit.Cucumber;
import cucumber.api.CucumberOptions;
import cucumber.api.SnippetType;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(plugin="pretty", snippets=SnippetType.CAMELCASE)
public class RunCukesTest {
}

6. ¾ßÌåµÄʵÏÖ

public class Account {
private Money balance = new Money();
public void deposit(Money amount) {
balance = balance.add(amount);
}
public Money getBalance() {
return balance;
}
}
public class CashSlot {
private int contents;
public int getContents() {
return contents;
}
public void dispense(int dollars){
contents = dollars;
}
}
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class Money {
private final int dollars;
private final int cents;
public Money() {
this.dollars = 0;
this.cents = 0;
}
public Money(int dollars, int cents) {
this.dollars = dollars;
this.cents = cents;
}
public Money(String amount) {
Pattern pattern = Pattern.compile("^[^\\d]*([\\d]+)\\.([\\d][\\d])$");
Matcher matcher = pattern.matcher(amount);
matcher.find();
this.dollars = Integer.parseInt(matcher.group(1));
this.cents = Integer.parseInt(matcher.group(2));
}
public int dollars() {
return dollars;
}
public int cents() {
return cents;
}
public Money add(Money amount){
int newCents = cents + amount.cents();
int newDollars = dollars + amount.dollars();
if (newCents >= 100){
newCents -= 100;
newDollars++;
}
return new Money(newDollars, newCents);
}
public Money minus(Money amount){
int newCents = cents - amount.cents();
int newDollars = dollars - amount.dollars();
if (newCents < 0){
newCents += 100;
newDollars--;
}
return new Money(newDollars, newCents);
}
@Override
public boolean equals(Object other){
boolean equal = false;
if (other instanceof Money){
Money otherMoney = (Money)other;
equal = (this.dollars() == otherMoney.dollars()
&& this.cents() == otherMoney.cents());
}
return equal;
}
@Override
public String toString() {
return String.format("$%01d.%02d", this.dollars(), this.cents());
}
}
public class Teller {
private CashSlot cashSlot;
public Teller(CashSlot cashSlot) {
this.cashSlot = cashSlot;
}
public void withdrawFrom(Account account, int dollars) {
cashSlot.dispense(dollars);
}
}

´ÓÉÏÃæµÄÀý×Ó¿ÉÒÔ¿´³ö£¬ÆäʵÏֵı¾ÖʺÍÔ­ÀíÈçÏ£º

Ò¹ÉîÁË£¬¸Ã˯ÁË£¬ÐÐΪÇý¶¯¿ª·¢µÄ½éÉܹýÒ»¶ÎÂ䣬ÐÐΪÇý¶¯¿ª·¢£¨BDD£©Äã×¼±¸ºÃÁËÂð£¿

 

 
   
4325 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

΢·þÎñ²âÊÔÖ®µ¥Ôª²âÊÔ
һƪͼÎÄ´øÄãÁ˽â°×ºÐ²âÊÔÓÃÀýÉè¼Æ·½·¨
È«ÃæµÄÖÊÁ¿±£ÕÏÌåϵ֮»Ø¹é²âÊÔ²ßÂÔ
È˹¤ÖÇÄÜ×Ô¶¯»¯²âÊÔ̽Ë÷
Ïà¹ØÎĵµ

×Ô¶¯»¯½Ó¿Ú²âÊÔʵ¼ù֮·
jenkins³ÖÐø¼¯³É²âÊÔ
ÐÔÄܲâÊÔÕï¶Ï·ÖÎöÓëÓÅ»¯
ÐÔÄܲâÊÔʵÀý
Ïà¹Ø¿Î³Ì

³ÖÐø¼¯³É²âÊÔ×î¼Ñʵ¼ù
×Ô¶¯»¯²âÊÔÌåϵ½¨ÉèÓë×î¼Ñʵ¼ù
²âÊԼܹ¹µÄ¹¹½¨ÓëÓ¦ÓÃʵ¼ù
DevOpsʱ´úµÄ²âÊÔ¼¼ÊõÓë×î¼Ñʵ¼ù