下面我们可以在 zero.feature 中多加几个场景(测试用例):

zero.feature

Feature: Compute factorial

In order to play with Lettuce

As beginners

We'll implement factorial

Scenario: Factorial of 0

Given I have the number 0

When I compute its factorial

Then I see the number 1

Scenario: Factorial of 1

Given I have the number 1

When I compute its factorial

Then I see the number 1

Scenario: Factorial of 2

Given I have the number 2

When I compute its factorial

Then I see the number 2

Scenario: Factorial of 3

Given I have the number 3

When I compute its factorial

Then I see the number 6

再次执行 lettuce 进行测试:

第四场景没通过,3!(3*2*1)=6 这个预期结果肯定是正确的,那就是代码的逻辑有问题吧!如果你

细心的话一定发现了 setup.py 中的代码并未真正实现阶乘,steps.py 文件中 factorial()函数,使其真

正可以处理阶乘:

steps.py

……

def factorial(number):

number = int(number)

if (number == 0) or (number == 1):

return 1

else:

return number*factorial(number-1)

因为 0 和 1 的阶乘都为 1,之前的代码直接判断计算的数字是否为 0 或 1,然后返回 1;如果是 2 的话

直接返回数字本身,对于 2 以上的数字并没进行计算。参照本文开头,通过递归的方式实现阶乘的代码,

现在才算完整的实现阶乘。再来执行 lettuce 进行验证吧!

lettuce 目录结构与执行过程

lettuce 是 Python 世界的 BDD 框架,开发人员主要与两类文件打交到,Feature 文件和相应的 Step

文件。Feature 文件是以 feature 为后缀名的文件,以 Given-When-Then 的方式描述了系统的场景

(scenarios)行为;Step 文件为普通的 Python 文件,Feature 文件中的每个 Given/When/Then 步骤在 Step

文件中都有对应的 Ruby 执行代码,两类文件通过正则表达式相关联。下面笔者大家简单对 lettuce 工程

的目录结构和执行过程进行分析。

目前大多数教程都建议采用以下目录结构,所有的文件(夹)都位于 features 文件夹下。

.../tests/features/test.feature

/step_definitions/test.py

/support/env.py

Feature 文件(如 test.feature)直接位于 features 文件夹下,可以为每个应用场景创建一个 Feature

文件;与 Feature 文件对应的 Step 文件(如 test.py)位于 step_definitions 子文件夹下;同时,存在

support 子文件夹,其下的 env.py 文件为环境配置文件。在这样的目录结构条件下执行 lettuce 命令,会首先执行 env.py 做前期准备工作,比如可以用 webdriver 新建浏览器窗口,然后 lettuce 将 test.py 文

件读入内存,最后执行 test.feature 文件,当遇到 Given/When/Then 步骤时,lettuce 将在 test.py 中搜

索是否有相应的 step,如果有,则执行相应的 Python 脚本。

这样的目录结构只是推荐的目录结构:对于 lettuce 而言,除了顶层的 features 文件夹是强制性的

之外,其它目录结构都不是强制性的,lettuce 将对 features 文件夹下的所有内容进行扁平化(flatten)

处理和首字母排序。具体来说,lettuce 在运行时,首先将递归的执行 features 文件夹下的所有 Python

文件(其中则包括 Step 文件),然后通过相同的方式执行 Feature 文件。但是,如果 features 文件夹下存

在support子文件夹,并且support下有名为env.py的文件,lettuce将首先执行该文件,然后执行support

下的其它文件,再递归执行 featues 下的其它文件。

比如有如下 lettuce 目录结构:

.../tests/features/a.feature

/a.py

/b.feature

/b.py

/other/c.feature

/other/f.py

/other/g.py

/setup_definitions/e.py

/support/c.py

/support/d.py

/support/env.py

此时执行 lettuce 命令,得到以下输出(部分)结果:

cmd.exe

env.py

c.py

d.py

a.py

b.py

f.py

g.py

e.py

……

上面结果即为 Python 文件的执行顺序,可以看出,support 文件夹下 env.py 文件首先被执行,其次按照字母排序执行 c.py 和 d.py;接下来,lettuce 将 features 文件夹下的所用文件(夹)扁平化,并按

字母顺序排序,从而先执行 a.py 和 b.py,而由于 other 文件夹排在 step_definitions 文件夹的前面,所

以先执行 other 文件夹下的 Ruby 文件(也是按字母顺序执行:先 f.py,然后 g.py),最后执行

step_definitions 下的 e.py。

当执行完所有 Python 文件后,lettuce 开始依次读取 Feature 文件,执行顺序也和前述一样,即:

a.feature --> b.feature --> c.feature

笔者还发现,这些 Python 文件甚至可以位于 features 文件夹之外的任何地方,只是需要在位于

features 文件夹之内的 Python 文件中 require 一下,比如在 env.py 中。