行为驱动测试方法已经在敏捷软件开发模式中普遍使用,通过使用标准化语言将客户需求人员,开发人员和测试人员关联在一起,让产品开发相关人员在沟通上保持一致。行为驱动开发是一种敏捷软件开发技术,它的英文全称是Behavior Driven Development,英文缩写BDD.它包括验收软件项目中的开发者,QA,非技术人员或商业参与者之间进行协作。在过去数年里,BDD开发模式得到了很大的发展,BDD的流行已然无法逆转。

lettuce 是实现BDD开发模式的一种测试框架,实现了使用自然语言来执行相关联测试的代码的需求。letttuce是基于Cucumber的一款非常易于使用的BDD工具,可以执行纯文本的功能描述。Lettuce使用Gherkina语言来描述测试功能,测试场景,测试步骤和测试结果,Gherkin语言支持超过40种语言,包括英文和中文,Gherkin语言使用的主要英文关键词有Scenario.Given,When,And,Then和But等,这些关键词也可以转换为中文关键词,例如“场景”“如果” “当”“那么”。根据用户story,需求人员或测试人员使用Gherkin语言编写好测试场景的每个执行步骤,Lettuce就会一步步地解析关键词右侧的自然语言并执行相应的代码。

关键词的含义如下:

1 Feature:特性,将多个测试用例集合到一起,对应于unittest中的test suite(测试用例集)。

2 Scenario:情景,用于描述一个用例,对应于unittest中的test case

3 Given:如果,用例开始执行前的一个前置条件,类似于unittest中setuo方法中的一些步骤。

4 When:当,用例开始执行时的一些关键操作步骤,类似于unittest中的以test开头的方法,比如执行一个单机元素的操作。

5 Then: 那么,验证结果,就是平时用例中的验证步骤,比如assert方法

6 And: 和,一个步骤中如果存在多个Given操作,后面的Given可以用And替代。

7 But:一个步骤中如果存在多个Then操作,第二个开始后面的Then可以用BUT替代。

使用Gherkin语言编写测试场景的执行步骤,并将执行步骤保存在扩展名为feature的文件中,每个.feature文件都要开始于Feature(功能)关键词,Feature之后的描述可以自定义,直到出现Scenario关键词。一个.feature文件中可以有多个Scenario.每个Scenario包含步骤(step)列表,不同步骤使用Given,when,Then,But,And这些关键词进行区分。

BDD开发模式的好处在于,可以将用户故事(scrum)或者需求和测试用例建立起一一对应的映射关系,保证开发和测试的目标与范围严格的和需求保持一致,可以更好的让需求方,开发者以及测试人员用唯一的需求进行相关的开发工作,防止对需求理解的不一致,并且BDD框架的测试结果很容易被参与者理解。

参考代码结构:

|lettuce

    |MyBDD

        |features

            - zero.feature

            - setps.py

##zero.feature

Feature: Compute sum  In order to play with Lettuce  As beginners  We'll implement sum
 Scenario: sum of 1,2    Given I have the number 1,2    When I compute its sum    Then I see the number 3  Scenario: sum of 1,4    Given I have the number 1,4    When I compute its sum    Then I see the number 5


##setps.py

def sum(a,b):    return a+b
@step('I have the numbers (\d+),(\d+)')def have_the_number(step, number1,number2):    # 将通过正则表达式匹配的数字存于全局变量world中    world.number1 = int(number1)    world.number2 = int(number2)
@step('I compute its sum')def compute_its_sum(step):    # 从全局变量world中取出匹配的数字,    # 计算其阶乘,并将结果再存回world中    world.sum = sum(world.number1,world.number2)
@step('I see the number (\d+)')def check_number(step, expected):    # 通过正则匹配到预期数字    expected = int(expected)    expected = int(expected)    # 断言计算阶乘结果是否等于预期    assert  world.sum == expected, "Got %d"