欢迎光临
梦想从学习开始!

PHP自动化验收测试快速入门| 小熊测试

本文主要介绍 PHP自动化验收测试快速入门| 小熊测试,小熊希望对大家的学习或者工作具有一定的参考学习价值,在测试领域有所提升和发展。

  欢迎来到Behat,Behat是行为驱动开发(BDD)的工具。在BDD中,你可以用对人友好的故事来描述程序的行为,也可以使用这些故事来做自动化测试。没错,这听起来是不是很酷?

  例如,想象下你要开发ls这个UNIX命令;客户可能会这么跟你说:

功能: ls

为了能看到的目录结构

作为一个UNIX用户

我需要能够列出当前目录的内容

场景: 列出目录中的2个文件

假如我在"test"目录中

并且这个目录有"foo"文件

同时这个目录有"bar"文件

当我运行"ls"后

那么我能看到

"""

bar

foo

"""

  在这个教程中,我们将向你演示Behat是如何把这个简单的故事作为测试来验证ls命令是像描述那样工作的。

  Behat可以被用来测试任何东西,包括使用Mink类库来测试与Web有关的行为。

  如果你想学习更多的测试“行为”的知识,请查看 故事包含什么?

  Behat的灵感来自于Ruby的Cucumber项目。

  安装

  Behat可以把你的用户故事作为测试的命令行工具,在开始之前,要确保你已安装的PHP版本高于5.3.1。

  使用composer安装

  通过composer来安装Behat是最简单的。

  在项目的根目录创建composer.json文件:

{

"require": {

"symfony/yaml": "2.1.13",

"symfony/translation": "2.3.24",

"symfony/console": "2.1.13",

"symfony/config": "2.3.24",

"symfony/dependency-injection": "2.1.13",

"symfony/event-dispatcher": "2.1.13",

"symfony/class-loader": "2.1.13",

"symfony/css-selector": "2.1.13",

"symfony/dom-crawler": "2.1.13",

"symfony/browser-kit": "2.1.13",

"symfony/finder": "2.1.13",

"symfony/process": "2.1.13",

"guzzle/guzzle": "3.3.1",

"fabpot/goutte": "1.0.1",

"instaclick/php-webdriver": "1.0.12",

"behat/gherkin": "4.3.0",

"behat/behat": "3.0.14",

"behat/mink": "1.5.0",

"behat/mink-extension": "2.0.1",

"behat/mink-browserkit-driver": "1.1.0",

"behat/mink-goutte-driver": "1.0.9",

"behat/mink-selenium2-driver": "1.1.1",

"behat/mink-zombie-driver": "1.1.0"

},

"minimum-stability": "dev",

"config": {

"bin-dir": "bin/"

}

}

  下载composer.phar运行:

  $ curl http://getcomposer.org/installer | php

  $ php composer.phar install

  执行完之后,你就可以用这个命令运行Behat了:

  $ ./vendor/behat/behat/bin/behat

  基本用法

  假设我们正在开发UNIX的ls命令,我们需要创建一个新的目录并且在这个目录中初始化Behat:

  $ mkdir ls_project

  $ cd ls_project

  $ ./vendor/behat/behat/bin/behat –init

  behat —init 会在当前目录下创建含有一些基础文件的features目录。

  定义你的feature

  Behat总是从feature文件开始,你可以描述和实现它。在这个例子中,功能是ls命令,它可以看成是整个UNIX系统的一个功能。我们需要先创建features/ls.feature文件:

  # language: zh-CN

  功能: ls

  为了能看到的目录结构

  作为一个UNIX用户

  我需要能够列出当前目录的内容

  每个功能都是使用这样的格式,一行描述功能,接下来的三行分别描述目标或者收益、角色、功能本身,如:

  为了<达到某些目标>

  作为<某类利益人>

  我想要<某个特性>

  虽然这部分内是必须的,但内容对Behat或者实际的测试来说并不重要。这部分最重要的是每个功能都有明确的描述,并且是很容易阅读理解的。

  定义场景

  接下来在features/ls.feature尾部添加场景:

  场景: 列出目录中的2个文件

  假如我在"test"目录中

  并且这个目录有"foo"文件

  同时这个目录有"bar"文件

  当我运行"ls"后

  那么我能看到

  """

  bar

  foo

  """

  “””这个特殊的语法只是为了界定多行字符串而使用的特殊语法。

  每个功能都有一个或者多个“场景”,用来描述功能在不同条件下有不同的行为。这将被转为测试的一部分,每个场景始终遵循这样的格式:

  场景: 一些场景的描述

  假如[一些上下文,设定状态]

  当[一些事件,执行行为]

  那么[得到结果,状态校验]

  在场景的每部分——上下文、行为和结果,都可以增加“并且”、“同时”、“而且”、“但是”这些关键字:

  场景: 一些场景的描述

  假如[一些上下文]

  并且[另外一些上下文]

  当[一些事件]

  同时[第二个事件发生]

  那么[得到结果]

  而且[另外的结果]

  但是[另外的结果]

  “那么”、“并且”、“但是”或者和其它开头的词语并没有实际的区别,这些词语只是让你的场景看上去更自然,有更好的可读性。

  执行Behat

  你已经定义好功能和场景了,你肯定希望看到Behat可以用了。在ls_project目录执行下面的命令:

  $ ./vendor/behat/behat/bin/behat

  如果一切正常运行,你可以看到这个:

$ behat

功能: ls

为了能看到的目录结构

作为一个UNIX用户

我需要能够列出当前目录的内容

场景: 列出目录中的2个文件    # features/ls.feature:7

假如 我在"test"目录中

并且 这个目录有"foo"文件

同时 这个目录有"bar"文件

当 我运行"ls"后

那么 我能看到

"""

bar

foo

"""

1 scenario (1 undefined)

5 steps (5 undefined)

0m0.54s (9.96Mb)

— FeatureContext has missing steps. Define them with these snippets:

/**

* @Given 我在:arg1目录中

*/

public function woZaiMuLuZhong($arg1)

{

throw new PendingException();

}

/**

* @Given 这个目录有:arg1文件

*/

public function zheGeMuLuYouWenJian($arg1)

{

throw new PendingException();

}

/**

* @When 我运行:arg1后

*/

public function woYunXingHou($arg1)

{

throw new PendingException();

}

/**

* @Then 我能看到

*/

public function woNengKanDao(PyStringNode $string)

{

throw new PendingException();

}

  实现步骤定义

  Behat会自动查找到features/ls.feature文件,并尝试把场景当成测试去执行。由于我们没有告诉Behat像“假如我在”test”目录中”这样的语句需要做什么,所以会出现上面的错误。Behat用正则表达式来匹配场景中的每一句话,并把这个正则表达式转换成每一个“步骤”。幸运的是,Behat可以自动打印出正则表达式,这样我们就不需要去创建每个步骤的定义:

/**

* @Given 我在:arg1目录中

*/

public function woZaiMuLuZhong($arg1)

{

throw new PendingException();

}

我们把Behat的建议添加到 features/bootstrap/FeatureContent.php中,重构参数$arg1为$dir:

use BehatBehatContextContext;

use BehatBehatContextSnippetAcceptingContext;

use BehatGherkinNodePyStringNode;

use BehatGherkinNodeTableNode;

/**

* Defines application features from the specific context.

*/

class FeatureContext implements Context, SnippetAcceptingContext

{

/**

* @Given 我在:dir目录中

*/

public function woZaiMuLuZhong($dir)

{

if (!file_exists($dir)) {

mkdir($dir);

}

chdir($dir);

}

}

  我们使用Behat建议的正则表达式,引号中的值(如:”test”)作为$dir变量,在方法内部,我们简单的创建目录并进入到这个目录中。

  以此类推,实现FeatureContent.php中剩下的3个步骤:

use BehatBehatContextContext;

use BehatBehatContextSnippetAcceptingContext;

use BehatGherkinNodePyStringNode;

use BehatGherkinNodeTableNode;

/**

* Defines application features from the specific context.

*/

class FeatureContext implements Context, SnippetAcceptingContext

{

/**

* @Given 我在:dir目录中

*/

public function woZaiMuLuZhong($dir)

{

if (!file_exists($dir)) {

mkdir($dir);

}

chdir($dir);

}

/**

* @Given 这个目录有:file文件

*/

public function zheGeMuLuYouWenJian($file)

{

touch($file);

}

/**

* @When 我运行:command后

*/

public function woYunXingHou($command)

{

exec($command, $output);

$this->output = trim(implode("", $output));

}

/**

* @Then 我能看到

*/

public function woNengKanDao(PyStringNode $string)

{

if ((string) $string !== $this->output) {

throw new Exception(

"Actual output is:" . $this->output

);

}

}

}

  当指定多行的步骤参数——像我们上面的场景中使用的三个引号(”””),这个值传递到步骤函数(如:$string)时实际上是一个对象,使用(string)$string或者$string->getRaw()可以把它转换成字符串。

  很好,现在你已经定义好所有的步骤,再次运行Behat:

$ ./vendor/behat/behat/bin/behat

功能: ls

为了能看到的目录结构

作为一个UNIX用户

我需要能够列出当前目录的内容

场景: 列出目录中的2个文件    # features/ls.feature:7

假如 我在"test"目录中  # FeatureContext::woZaiMuLuZhong()

并且 这个目录有"foo"文件 # FeatureContext::zheGeMuLuYouWenJian()

同时 这个目录有"bar"文件 # FeatureContext::zheGeMuLuYouWenJian()

当 我运行"ls"后      # FeatureContext::woYunXingHou()

那么 我能看到         # FeatureContext::woNengKanDao()

"""

bar

foo

"""

1 scenario (1 passed)

5 steps (5 passed)

0m0.56s (10.06Mb)

  成功了!Behat执行了所有步骤——创建新的目录,创建2个文件并且执行ls命令;然后对比实际结果和期望结果。

  当然,你可以很容易地添加更多的场景和步骤。

  Behat基础知识

  当你运行 behat —init,它会把目录初始化成这样:

  .

  └── features

  └── bootstrap

  └── FeatureContext.php

  2 directories, 1 file

  任何和Behat有关的文件都在features目录,它由这三个基本区域:

  features/ – Behat执行目录中所有的 *.feature文件

  features/bootstrap – 在这个目录中所有的*.php文件在执行任何步骤前都会自动加载

  features/bootstrap/FeatureContext.php – 这个文件是每个场景步骤被执行的上下文类

  features基础知识

  正如你所看到的,功能描述是一个简单的、可读的纯文本文件,使用Gherkin格式。每个功能描述文件都遵循这些基本规则:

  每个*.feature文件通常只包含一个“功能”(如ls命令或者用户注册功能);

  每个功能使用关键字“功能”开头,紧跟着是标题和三行缩进的功能定义;

  一个功能通常会包含一序列场景,在第一个场景前的内容都当成是功能描述;

  每个场景都以“场景”或“剧本”开头,关键字之后紧跟一个简短的场景描述;

  场景有一序列的步骤,每个都以“假如”、“当”、“那么”、“但是”和“并且”这些关键字开头,对于Behat来说这些关键字是没有区别的,你应该把它们作用于一致的场景。

  了解更多“ Writing Features – Gherkin Language ”

  steps基础知识

  在每个步骤中,你需要告诉Behat有“失败”发生的话,你需要抛出一个异常;Behat没有自己的断言工具,但你可以使用任何可以进行断言的工具(比如PHPUnit)。

  如果没有任何异常或者失败的断言,Behat认为是“通过”的。

  了解更多“ Defining Reusable Actions – Step Definitions ”

  上下文类FeatureContent

  Behat会为每个场景创建一个上下文对象,并在这个对象中执行所有的场景步骤。也就是说如果你需要在不同的步骤共享变量,你可以很简单地在上下文对象中使用属性。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小熊分享邦(www.xxfxb.com),希望大家能坚持软件测试之路,谢谢。

赞(0) 打赏
未经允许不得转载:小熊分享邦 » PHP自动化验收测试快速入门| 小熊测试

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏