Numpy 基于BDD方式的测试

行为驱动开发(BDD)是另一个你可能已经碰到过的流行词汇。使用BDD时,我们首先需要依据某些约定和规则,用英语描述被测系统的预期行为。在本攻略中,我们将看到此类约定的一个例子。

BDD方式背后隐藏的想法是,让不会编程的人,能够以某种方式,编写测试代码的主体部分。这些人可以编写功能点(feature),即包括若干步骤的语句。每个步骤差不多都可以与我们编写的单元测试中的内容(例如用NumPy编写的测试语句)对应。目前存在很多Python的BDD框架。本攻略将使用Lettuce框架测试阶乘函数。

具体步骤

下面将介绍怎样安装Lettuce、建立测试环境和编写测试文档。

  1. 安装Lettuce。

为了安装Lettuce,请运行下列两条命令之一。

pip install lettuce
sudo easy_install lettuce
  1. 建立测试环境。

用Lettuce测试阶乘函数,需要按要求组织目录结构。在tests目录中,需要有一个features目录。在features目录中,要包含一个factorial.feature文件和一个steps.py文件。steps.py文件的内容是功能描述和测试代码。

./tests:
features

./tests/features:
factorial.feature  steps.py
  1. 编写测试文档。

提炼业务需求是一项艰巨的工作,而把它们用适合测试的方式表达出来就更难了。幸好本攻略的业务需求相当简单,我们只需要把不同的输入值和它们对应的期望的输出值写出来就可以。

我们需要定义不同的场景(scenario),每个场景包括Given、When和Then三个不同类型的区段。每种类型的区段对应不同的测试步骤。我们为阶乘功能点定义了下列三个场景。

Feature: Compute 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 3
        Given I have the number 3 
        When I compute its factorial 
        Then I see the number 1, 2, 6

  1. 定义步骤。

与上述场景中描述的测试步骤对应,我们将定义若干方法。需要特别注意用来标记方法的文本,其内容和场景描述中的区段内容是匹配的。可以用正则表达式从区段内容中提取出需要的输入参数。

在前面两个场景中,我们需要匹配数字。在最后一个场景中,我们需要匹配字符串。NumPy中的fromstring函数用来从字符串创建一个NumPy数组,该字符串由逗号分隔的整数构成。下面的代码用来对上述场景进行测试。

from lettuce import *
import numpy

@step('I have the number (\d+)')
def have_the_number(step, number):
    world.number = int(number)

@step('I compute its factorial')
def compute_its_factorial(step):
    world.number = factorial(world.number)

@step('I see the number (.*)')
def check_number(step, expected):
    expected = numpy.fromstring(expected, dtype=int,sep=',')numpy.testing.assert_equal(world.number, expected, \
"Got %s" % world.number)

def factorial(n):
    if n == 0:
        return 1

    if n 
  1. 执行测试。

执行测试时,首先进入tests目录,然后键入如下命令。

$ lettuce

Feature: Compute factorial        # \features\factorial.feature:1

Scenario: Factorial of 0        # \features\factorial.feature:3
    Given I have the number 0     # \features\steps.py:5
    When I compute its factorial  # \features\steps.py:9
    Then I see the number 1       # \features\steps.py:13

Scenario: Factorial of 1        # \features\factorial.feature:8
    Given I have the number 1     # \features\steps.py:5
    When I compute its factorial  # \features\steps.py:9
    Then I see the number 1       # \features\steps.py:13

Scenario: Factorial of 3        # \features\factorial.feature:13
    Given I have the number 3     # \features\steps.py:5
    When I compute its factorial  # \features\steps.py:9
    Then I see the number 1, 2, 6 # \features\steps.py:13

1 feature (1 passed)
3 scenarios (3 passed)
9 steps (9 passed)

攻略小结

我们定义了一个包含三个场景的功能点,每个场景都包括若干步骤。我们使用NumPy.testing模块中的函数对相关的步骤进行了测试,并使用fromstring函数利用特定格式的字符串创建了一个NumPy数组。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程