動作駆動開発 (BDD) アプローチを使用した Laravel アプリケーションの開発に関するシリーズへようこそ。フルスタック BDD は複雑で恐ろしいように思えるかもしれません。これを実現する方法は開発者の数と同じくらいたくさんあります。
このシリーズでは、Behat と PhpSpec を使用して Laravel アプリケーションを最初から設計する方法を説明します。
BDD には一般的に多くのリソースがありますが、Laravel 固有の資料を見つけるのは困難です。したがって、このシリーズでは、他の多くの場所で読むことができる一般的な内容ではなく、Laravel 関連の側面に重点を置きます。
動作を説明するとき (ストーリーや仕様の作成とも呼ばれます)、アウトサイドインのアプローチを使用します。これは、新しい機能を構築するたびに、ユーザー ストーリー全体を書くことから始めることを意味します。これは通常、顧客または利害関係者の観点からのものです。
これを実行すると何が起こると予想されますか? 块引用>既存のコードをリファクタリングしない限り、失敗した赤いステップに到達しない限り、コードを記述することはできません。
場合によっては、取り組んでいるストーリーや機能 (私はこの 2 つの単語を同じ意味で使用します) の小さな部分に繰り返し取り組む必要があります。これは通常、PhpSpec を使用して仕様を記述することを意味します。場合によっては、ストーリー全体が (受け入れレベルで) 通過するまでに、統合レベルまたはユニット レベルで複数の反復が必要になることがあります。これだけ聞くと複雑そうに思えますが、実際はそうではありません。私は実践しながら学ぶことを強く信じているので、実際のコードを書き始めると、すべてがより意味のあるものになると思います。
4 つの異なるレベルでストーリーと仕様を書いていきます:
1. 承諾
ほとんどの場合、機能スイートは受け入れ層として機能します。機能スイートで機能を説明する方法は、(自動ブラウザ フレームワークを使用して) 承認ストーリーを作成する方法と非常に似ているため、重複する部分が多くなります。
ストーリーが顧客の視点から行動を説明している限り、それらは受け入れストーリーとして適格です。 Symfony DomCrawler を使用してアプリケーションの出力をテストします。このシリーズの後半では、JavaScript も実行できる実際のブラウザでテストする必要があることが判明するかもしれません。ブラウザーを介したテストでは、スイートの実行中に 1 時間ごとのテスト環境が確実に読み込まれるようにする必要があるため、いくつかの新しい問題が追加されます。
2. 機能
私たちの機能スイートでは、Laravel アプリケーションにアクセスできるようになります。これは非常に便利です。まず、環境を簡単に区別できるようになります。次に、ブラウザを経由しないため、テスト スイートが高速になります。新しい機能を実装したいときは、Behat を使用して機能スイートのストーリーを作成します。
3. 統合
私たちの統合スイートは、Laravel へのアクセスを必ずしも必要としないアプリケーションのコア部分の動作をテストします。統合スイートは、多くの場合、Behat のストーリーと PhpSpec 仕様の混合物です。
4.ユニット
私たちの単体テストは PhpSpec で書かれ、アプリケーションの中核にある独立した小さなユニットをテストします。エンティティ、値オブジェクトなどにはすべて仕様があります。
場合###
このシリーズでは、次回から時間を追跡するシステムを構築していきます。まず、Behat トレイトを記述して外部の動作を説明します。アプリケーションの内部動作は PhpSpec を使用して説明します。これら 2 つのツールを併用すると、構築しているアプリケーションの品質に満足できるようになります。主に機能と仕様を次の 3 つのレベルで記述します。
###特徴###
統合###ユニット###
- 私たちの機能スイートでは、ヘッドレス モードでアプリケーションの HTTP 応答をスクレイピングします。つまり、ブラウザーを経由しません。これにより、Laravel との対話が容易になり、一連の機能が受け入れレイヤーとしても機能できるようになります。
- 後で、より複雑な UI が作成され、JavaScript もテストする必要がある場合は、専用の受け入れスイートを追加する可能性があります。このシリーズはまだ進行中ですので、お気軽にコメント欄にご提案をお寄せください。
私たちの設定
このチュートリアルでは、Laravel (4.2) をクリーンインストールして実行していることを前提としていることに注意してください。できれば、Laravel Homestead も使用することをお勧めします。これは、このコードを作成するときに使用したものです。
実際の作業を開始する前に、Behat と PhpSpec が稼働していることを確認してください。まず、新しい Laravel プロジェクトを開始するときは常に、少しクリーンアップして不要なものを削除するのが好きです。
リーリーこれらのファイルを削除する場合は、必ず
composer.jsonファイルをそれに応じて更新してください:
リーリー ###確かに:### リーリーこれで、必要な BDD ツールを導入する準備が整いました。
require-devセクションを
に追加するだけです。composer.json
:"require": { "laravel/framework": "4.2.*" }, "require-dev": { "behat/behat": "~3.0", "phpspec/phpspec": "~2.0", "phpunit/phpunit": "~4.1" },“我们为什么要引入 PHPUnit?”你可能在想?在本系列中,我们不会编写优秀的 PHPUnit 测试用例,但断言与 Behat 一起是一个方便的工具。我们将在本文后面编写第一个功能时看到这一点。
请记住在修改
composer.json
后更新依赖项:$ composer update --dev我们即将完成安装和设置。 PhpSpec 开箱即用:
$ vendor/bin/phpspec run 0 specs 0 examples 0ms但是 Behat 需要使用
--init
选项快速运行才能设置所有内容:$ vendor/bin/behat --init +d features - place your *.feature files here +d features/bootstrap - place your context classes here +f features/bootstrap/FeatureContext.php - place your definitions, transformations and hooks here $ vendor/bin/behat No scenarios No steps 0m0.14s (12.18Mb)第一个命令创建了一个闪亮的新
FeatureContext
类,我们可以在其中编写功能所需的步骤定义:<?php use Behat\Behat\Context\SnippetAcceptingContext; use Behat\Gherkin\Node\PyStringNode; use Behat\Gherkin\Node\TableNode; /** * Behat context class. */ class FeatureContext implements SnippetAcceptingContext { /** * Initializes context. * * Every scenario gets its own context object. * You can also pass arbitrary arguments to the context constructor through behat.yml. */ public function __construct() { } }编写我们的第一个功能
我们的第一个功能非常简单:我们只需确保新的 Laravel 安装以“您已到达”来迎接我们。在主页上。我还添加了一个相当愚蠢的
Given
步骤,假设我登录了
,这仅用于显示在我们的功能中与 Laravel 交互是多么容易。从技术上讲,我将这种类型的功能归类为功能测试,因为它与框架交互,但它也可以作为验收测试,因为我们不会看到通过浏览器测试运行类似测试有任何不同的结果工具。现在我们将坚持使用我们的功能测试套件。
继续创建一个
welcome.feature
文件并将其放入features/functions
:# features/functional/welcome.feature Feature: Welcoming developer As a Laravel developer In order to proberly begin a new project I need to be greeted upon arrival Scenario: Greeting developer on homepage Given I am logged in When I visit "/" Then I should see "You have arrived."通过将功能特性放在
featured
目录中,我们以后可以更轻松地管理我们的套件。我们不希望不需要 Laravel 的集成类型功能必须等待缓慢的功能套件。我喜欢让事情保持美观和干净,所以我相信我们应该为我们的功能套件提供一个专用的功能上下文,以便我们可以访问 Laravel。您可以继续复制现有的
FeatureContext
文件并将类名称更改为LaravelFeatureContext
。为此,我们还需要一个behat.yml
配置文件。在项目的根目录中创建一个并添加以下内容:
default: suites: functional: paths: [ %paths.base%/features/functional ] contexts: [ LaravelFeatureContext ]我认为这里的 YAML 是非常不言自明的。我们的功能套件将在
functioning
目录中查找功能,并通过LaravelFeatureContext
运行它们。如果我们此时尝试运行 Behat,它会告诉我们实现必要的步骤定义。我们可以使用以下命令让 Behat 将空脚手架方法添加到
LaravelFeatureContext
中:$ vendor/bin/behat --dry-run --append-snippets $ vendor/bin/behat Feature: Welcoming developer As a Laravel developer In order to proberly begin a new project I need to be greeted upon arival Scenario: Greeting developer on homepage # features/functional/welcome.feature:6 Given I am logged in # LaravelFeatureContext::iAmLoggedIn() TODO: write pending definition When I visit "/" # LaravelFeatureContext::iVisit() Then I should see "You have arrived." # LaravelFeatureContext::iShouldSee() 1 scenario (1 pending) 3 steps (1 pending, 2 skipped) 0m0.28s (12.53Mb)现在,正如您从输出中看到的那样,我们已准备好开始实施第一个步骤:
鉴于我已登录
。Laravel 附带的 PHPUnit 测试用例允许我们执行诸如
$this->be($user)
之类的操作,它会登录给定用户。最终,我们希望能够像使用 PHPUnit 一样与 Laravel 交互,所以让我们继续编写“我们希望拥有”的步骤定义代码:/** * @Given I am logged in */ public function iAmLoggedIn() { $user = new User; $this->be($user); }这当然行不通,因为 Behat 不知道 Laravel 的具体内容,但我很快就会向您展示让 Behat 和 Laravel 很好地协同工作是多么容易。
如果您查看 Laravel 源代码并找到
Illuminate\Foundation\Testing\TestCase
类(默认测试用例扩展自该类),您会发现从 Laravel 4.2 开始,一切都已更改转移到一个特质。ApplicationTrait
现在负责启动Application
实例、设置 HTTP 客户端并为我们提供一些辅助方法,例如be()
。这非常酷,主要是因为这意味着我们可以将其拉入我们的 Behat 上下文中,几乎不需要任何设置。我们还可以访问
AssertionsTrait
,但这仍然与 PHPUnit 相关。当我们引入特征时,我们需要做两件事。我们需要一个
setUp()
方法,如Illuminate\Foundation\Testing\TestCase
类中的方法,并且需要一个createApplication()
方法,如默认 Laravel 测试用例中的方法。其实我们直接复制这两个方法就可以了。只有一件事需要注意:在 PHPUnit 中,方法
setUp()
会在每次测试之前自动调用。为了在 Behat 中实现相同的效果,我们可以使用@BeforeScenario
注释。将以下内容添加到您的
LaravelFeatureContext
:use Illuminate\Foundation\Testing\ApplicationTrait; /** * Behat context class. */ class LaravelFeatureContext implements SnippetAcceptingContext { /** * Responsible for providing a Laravel app instance. */ use ApplicationTrait; /** * Initializes context. * * Every scenario gets its own context object. * You can also pass arbitrary arguments to the context constructor through behat.yml. */ public function __construct() { } /** * @BeforeScenario */ public function setUp() { if ( ! $this->app) { $this->refreshApplication(); } } /** * Creates the application. * * @return \Symfony\Component\HttpKernel\HttpKernelInterface */ public function createApplication() { $unitTesting = true; $testEnvironment = 'testing'; return require __DIR__.'/../../bootstrap/start.php'; }非常简单,看看我们运行 Behat 时得到的结果:
$ vendor/bin/behat Feature: Welcoming developer As a Laravel developer In order to proberly begin a new project I need to be greeted upon arival Scenario: Greeting developer on homepage # features/functional/welcome.feature:6 Given I am logged in # LaravelFeatureContext::iAmLoggedIn() When I visit "/" # LaravelFeatureContext::iVisit() TODO: write pending definition Then I should see "You have arrived." # LaravelFeatureContext::iShouldSee() 1 scenario (1 pending) 3 steps (1 passed, 1 pending, 1 skipped) 0m0.73s (17.92Mb)绿色的第一步,这意味着我们的设置正在运行!
接下来,我们可以实现
当我访问
步骤。这个非常简单,我们可以简单地使用ApplicationTrait
提供的call()
方法。一行代码即可实现:/** * @When I visit :uri */ public function iVisit($uri) { $this->call('GET', $uri); }最后一步,
然后我应该看到
,需要更多一点,我们需要引入两个依赖项。我们需要 PHPUnit 来进行断言,并且需要 Symfony DomCrawler 来搜索“您已到达”。文本。我们可以这样实现:
use PHPUnit_Framework_Assert as PHPUnit; use Symfony\Component\DomCrawler\Crawler; ... /** * @Then I should see :text */ public function iShouldSee($text) { $crawler = new Crawler($this->client->getResponse()->getContent()); PHPUnit::assertCount(1, $crawler->filterXpath("//text()[. = '{$text}']")); }这与您使用 PHPUnit 时编写的代码几乎相同。
filterXpath()
部分有点令人困惑,我们现在不用担心它,因为它有点超出了本文的范围。请相信我,它有效。最后一次跑步是个好消息:
$ vendor/bin/behat Feature: Welcoming developer As a Laravel developer In order to proberly begin a new project I need to be greeted upon arival Scenario: Greeting developer on homepage # features/functional/welcome.feature:6 Given I am logged in # LaravelFeatureContext::iAmLoggedIn() When I visit "/" # LaravelFeatureContext::iVisit() Then I should see "You have arrived." # LaravelFeatureContext::iShouldSee() 1 scenario (1 passed) 3 steps (3 passed) 0m0.82s (19.46Mb)该功能正在按预期工作,并且开发人员在抵达时受到欢迎。
结论
完整的
LaravelFeatureContext
现在应该与此类似:call('GET', $uri); } /** * @Then I should see :text */ public function iShouldSee($text) { $crawler = new Crawler($this->client->getResponse()->getContent()); PHPUnit::assertCount(1, $crawler->filterXpath("//text()[. = '{$text}']")); } }随着我们继续使用 BDD 开发新的 Laravel 应用程序,我们现在已经有了一个非常好的基础。我希望我已经向您证明了让 Laravel 和 Behat 很好地协同工作是多么容易。
我们在第一篇文章中讨论了许多不同的主题。不用担心,随着本系列的继续,我们将更深入地研究一切。如果您有任何问题或建议,请留言。
以上がLaravel、BDD、そしてあなたから始めましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。