イントロダクションIntroduction
Laravelはユニットテストも考慮して構築されています。実際、PHPUnitをサポートしており、最初から含まれています。アプリケーションのためにphpunit.xml
ファイルも最初から準備されています。さらにフレームワークはアプリケーションを記述的にテストするために便利なヘルパメソッドも持っています。Laravel is built with testing in
mind. In fact, support for testing with PHPUnit is
included out of the box, and a
phpunit.xml
file is already setup for
your application. The framework also ships with
convenient helper methods allowing you to
expressively test your applications.
ExampleTest.php
ファイルがtests
ディレクトリに提供されています。新しいLaravelアプリケーションをインストールした後、そのままphpunit
をコマンドラインで実行し試してみてください。An ExampleTest.php
file is provided in the tests
directory. After installing a new Laravel
application, simply run phpunit
on the
command line to run your tests.
テスト動作環境Test Environment
テスト実行時にLaravelは、設定環境を自動的にtesting
へセットします。そしてLaravelはセッションととキャッシュの設定ファイルをテスト環境で呼び出します。両方のドライバはテスト環境ではarray
にセットされます。つまりデータはテストを実行している間のみ存在しているということです。When running tests, Laravel will
automatically set the configuration environment to
testing
. Laravel automatically
configures the session and cache to the
array
driver while testing, meaning no
session or cache data will be persisted while
testing.
必要であれば他のテスト設定環境を自由に作成することもできます。testing
動作環境変数はphpunit.xml
の中で設定されています。テスト実行前には、config:clear
Artisanコマンドを実行し、設定キャッシュをクリアするのを忘れないでください。You are free to create other
testing environment configurations as necessary. The
testing
environment variables may be
configured in the phpunit.xml
file, but
make sure to clear your configuration cache using
the config:clear
Artisan command before
running your tests!
テストの定義と実行Defining & Running Tests
新しいテストケースを作成するには、make:test
Artisanコマンドを使います。To create a
new test case, use the make:test
Artisan command:
php artisan make:test UserTest
上記のコマンドにより、tests
ディレクトリ中に新しいUserTest
クラスが設置されます。それから、いつもの通りPHPUnitを使ってテストメソッドを定義してください。テストを実行するには、ただターミナルでphpunit
コマンドを実行するだけです。This command will place a new
UserTest
class within your
tests
directory. You may then define
test methods as you normally would using PHPUnit. To
run your tests, simply execute the
phpunit
command from your
terminal:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class UserTest extends TestCase
{
/**
* 基本的なテスト例
*
* @return void
*/
public function testExample()
{
$this->assertTrue(true);
}
}
注意:
setUp
メソッドを定義する場合はparent::setUp
を確実に呼び出してください。Note: If you define your ownsetUp
method within a test class, be sure to callparent::setUp
.
アプリケーションのテストApplication Testing
Laravelはアプリケーションに送るHTTPリクエストの作成、出力の検査、さらにフォームの入力もスラスラと書けるAPIを提供しています。例としてtests
ディレクトリに含まれるExampleTest.php
ファイルを見てください。Laravel provides a very fluent
API for making HTTP requests to your application,
examining the output, and even filling out forms.
For example, take a look at the
ExampleTest.php
file included in your
tests
directory:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
/**
* 基本的な機能テストの例
*
* @return void
*/
public function testBasicExample()
{
$this->visit('/')
->see('Laravel 5')
->dontSee('Rails');
}
}
visit
メソッドはアプリケーションに対するGET
リクエストを作成します。see
メソッドは指定されたテキストがアプリケーションから返されるレスポンスの中に存在することをアサートします。dontSee
メソッドは指定したテキストがアプリケーションレスポンスの中へ返されていないことをアサートします。これはLaravelで使用できる最も基本的なアプリケーションテストです。The visit
method
makes a GET
request into the
application. The see
method asserts
that we should see the given text in the response
returned by the application. The
dontSee
method asserts that the given
text is not returned in the application response.
This is the most basic application test available in
Laravel.
アプリケーションとの関わりInteracting With Your Application
もちろんシンプルに指定したレスポンスの中にテキストが現れるかアサートする以上のことが可能です。リンクのクリックとフォームの埋め込みを見てみましょう。Of course, you can do much more than simply assert that text appears in a given response. Let's take a look at some examples of clicking links and filling out forms:
リンクのクリックClicking Links
このテストではアプリケーションへのリクエストを作成し、帰ってきたレスポンス中のリンクを「クリック」、それから指定されたURIに到達することをアサートします。たとえば"About Us"のテキスト値を持つレスポンスの中のリンクがあると仮定しましょう。In this test, we will make a request to the application, "click" a link in the returned response, and then assert that we landed on a given URI. For example, let's assume there is a link in our response that has a text value of "About Us":
<a href="/about-us">About Us</a>
では、このリンクをクリックし、正しいページに到達したことをアサートしましょう。Now, let's write a test that clicks the link and asserts the user lands on the correct page:
public function testBasicExample()
{
$this->visit('/')
->click('About Us')
->seePageIs('/about-us');
}
フォームの埋め込みWorking With Forms
Laravelはさらにフォームをテストするために多くのメソッドを提供しています。type
、select
、check
、attach
、press
メソッドはフォーム入力の全てを操作させてくれます。たとえば、アプリケーションの登録ページにこのフォームがあると考えてください。Laravel also provides several
methods for testing forms. The type
,
select
, check
,
attach
, and press
methods
allow you to interact with all of your form's
inputs. For example, let's imagine this form exists
on the application's registration page:
<form action="/register" method="POST">
{{ csrf_field() }}
<div>
Name: <input type="text" name="name">
</div>
<div>
<input type="checkbox" value="yes" name="terms"> Accept Terms
</div>
<div>
<input type="submit" value="Register">
</div>
</form>
このフォームを完全に埋め、結果を確認するテストが書けます。We can write a test to complete this form and inspect the result:
public function testNewUserRegistration()
{
$this->visit('/register')
->type('Taylor', 'name')
->check('terms')
->press('Register')
->seePageIs('/dashboard');
}
もちろん、フォームにラジオボタンやドロップボックスのような他の入力が含まれていても、同様にそうしたフィールドを簡単に埋めることができます。フォーム操作メソッドのリストを見てください。Of course, if your form contains other inputs such as radio buttons or drop-down boxes, you may easily fill out those types of fields as well. Here is a list of each form manipulation method:
メソッドMethod | 説明Description |
---|---|
$this->type($text,
$elementName) $this->type($text,
$elementName) |
指定したフィールドに「タイプ」します。"Type" text into a given field. |
$this->select($value,
$elementName) $this->select($value,
$elementName) |
ラジオボタンかドロップダウンフィールドを「選択」します。"Select" a radio button or drop-down field. |
$this->check($elementName) $this->check($elementName) |
チェックボックスフィールドを「チェック」します。"Check" a checkbox field. |
$this->uncheck($elementName) $this->uncheck($elementName) |
"Uncheck" a checkbox field."Uncheck" a checkbox field. |
$this->attach($pathToFile,
$elementName) $this->attach($pathToFile,
$elementName) |
フォームにファイルを「添付」します。"Attach" a file to the form. |
$this->press($buttonTextOrElementName) $this->press($buttonTextOrElementName) |
指定したテキストか名前のボタンを「押し」ます。"Press" a button with the given text or name. |
ファイル添付操作Working With Attachments
フォームにfile
入力タイプが含まれているならば、attach
メソッドを使いフォームにファイルを添付できます。If your form contains
file
input types, you may attach files
to the form using the attach
method:
public function testPhotoCanBeUploaded()
{
$this->visit('/upload')
->type('File Name', 'name')
->attach($absolutePathToFile, 'photo')
->press('Upload')
->see('Upload Successful!');
}
JSON APIのテストTesting JSON APIs
さらにLaravelはJSON
APIとそれらのレスポンスをテストするために、多くのヘルパも用意しています。たとえば、get
、post
、put
、patch
、delete
メソッドは各HTTP動詞でのリクエストを発行するために使用します。また簡単にデータとヘッダをメソッドに渡すこともできます。手始めに、/user
に対するPOST
リクエストを作成し、JSONフォーマットで指定指定した配列が返ってくることをアサートするテストを書いてみましょう。Laravel also provides several
helpers for testing JSON APIs and their responses.
For example, the get
,
post
, put
,
patch
, and delete
methods
may be used to issue requests with various HTTP
verbs. You may also easily pass data and headers to
these methods. To get started, let's write a test to
make a POST
request to
/user
and assert that a given array was
returned in JSON format:
<?php
class ExampleTest extends TestCase
{
/**
* 基本的な機能テストの例
*
* @return void
*/
public function testBasicExample()
{
$this->json('POST', '/user', ['name' => 'Sally'])
->seeJson([
'created' => true,
]);
}
}
seeJson
メソッドは渡された配列をJSONに変換します。次にそのJSONが、JSONレスポンス全体のいずれかに現れるかを確認します。ですから、他のプロパティーがJSONレスポンスに含まれていたとしても、指定した部分が存在する限り、テストはパスします。The seeJson
method
converts the given array into JSON, and then
verifies that the JSON fragment occurs
anywhere within the entire JSON
response returned by the application. So, if there
are other properties in the JSON response, this test
will still pass as long as the given fragment is
present.
JSONと一致するか厳格に検証Verify Exact JSON Match
指定した配列がアプリケーションから返されるJSONと厳格に一致するかを確認したい場合は、seeJsonEquals
メソッドを使用してください。If you would like to verify that
the given array is an exact match
for the JSON returned by the application, you should
use the seeJsonEquals
method:
<?php
class ExampleTest extends TestCase
{
/**
* 基本的な機能テストの例
*
* @return void
*/
public function testBasicExample()
{
$this->json('POST', '/user', ['name' => 'Sally'])
->seeJsonEquals([
'created' => true,
]);
}
}
JSON構造の合致Verify Structural JSON Match
それには、seeJsonStructure
メソッドを使い、ネストしたキーのリストを渡します。It is also possible to verify
that a JSON response adheres to a specific
structure. For this, you should use the
seeJsonStructure
method and pass it a
list of (nested) keys:
<?php
class ExampleTest extends TestCase
{
/**
* 基本的な機能テストの例
*
* @return void
*/
public function testBasicExample()
{
$this->get('/user/1')
->seeJsonStructure([
'name',
'pet' => [
'name', 'age'
]
]);
}
}
上の例ではname
および、name
とage
を持つネストしたpet
オブジェクトを受け取ることを期待しています。seeJsonStructure
は、レスポンスが余計なキーを含んていても失敗しません。たとえば、pet
がweight
属性を持っていても、テストをパスします。The above example illustrates an
expectation of receiving a name
and a
nested pet
object with its own
name
and age
.
seeJsonStructure
will not fail if
additional keys are present in the response. For
example, the test would still pass if the
pet
had a weight
attribute.
*
を使い、戻ってきたJSON構造がリストを持っていること、そして各リストが最低でも持っている属性を指定することもできます。You may use the *
to
assert that the returned JSON structure has a list
where each list item contains at least the
attributes found in the set of values:
<?php
class ExampleTest extends TestCase
{
/**
* 基本的な機能テストの例
*
* @return void
*/
public function testBasicExample()
{
// 各ユーザはid、name、email属性を最低でも持っていることを宣言
$this->get('/users')
->seeJsonStructure([
'*' => [
'id', 'name', 'email'
]
]);
}
}
*
記述法はネストもできます。次の例の場合、JSONレスポンスの各ユーザは指定されている属性を持っており、各ユーザの各ペットも指定されている属性を持っていることを宣言します。You may also nest the
*
notation. In this case, we will
assert that each user in the JSON response contains
a given set of attributes and that each pet on each
user also contains a given set of
attributes:
$this->get('/users')
->seeJsonStructure([
'*' => [
'id', 'name', 'email', 'pets' => [
'*' => [
'name', 'age'
]
]
]
]);
セッション/認証Sessions / Authentication
Laravelはテスト時にセッションを操作するたくさんのヘルパも提供しています。1つ目は指定した配列をセッションに保存するwithSession
メソッドです。これはアプリケーションのリクエストをテストする前に、データをセッションにロードしたい場合に便利です。Laravel provides several helpers
for working with the session during testing. First,
you may set the session data to a given array using
the withSession
method. This is useful
for loading the session with data before testing a
request to your application:
<?php
class ExampleTest extends TestCase
{
public function testApplication()
{
$this->withSession(['foo' => 'bar'])
->visit('/');
}
}
もちろん認証済みのユーザのようなユーザ状態をセッションへ保持するのは一般的です。actingAs
ヘルパメソッドは現在認証済みのユーザを指定する簡単な手段を提供します。たとえば、モデルファクトリでユーザを生成し、認証してみましょう。Of course, one common use of the
session is for maintaining user state, such as the
authenticated user. The actingAs
helper
method provides a simple way to authenticate a given
user as the current user. For example, we may use a
model factory[#model-factories] to generate
and authenticate a user:
<?php
class ExampleTest extends TestCase
{
public function testApplication()
{
$user = factory(App\User::class)->create();
$this->actingAs($user)
->withSession(['foo' => 'bar'])
->visit('/')
->see('Hello, '.$user->name);
}
}
ユーザの認証にどのガードを使用するかを指定したい場合、actingAs
メソッドの第2引数にガード名を渡します。You may also specify which guard
should be used to authenticate the given user by
passing the guard name as the second argument to the
actingAs
method:
$this->actingAs($user, 'backend')
ミドルウェアの無効化Disabling Middleware
アプリケーションをテストするとき、いくつかのテストではミドルウェアを無効にするほうが便利だと気がつくでしょう。これによりミドルウェアに関わらずにルートやコントローラーのテストが可能になります。LaravelはシンプルなWithoutMiddleware
トレイトを用意しており、これを使えば自動的にテストクラスのミドルウェアを無効にできます。When testing your application,
you may find it convenient to disable
middleware[/docs/{{version}}/middleware] for
some of your tests. This will allow you to test your
routes and controller in isolation from any
middleware concerns. Laravel includes a simple
WithoutMiddleware
trait that you can
use to automatically disable all middleware for the
test class:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
use WithoutMiddleware;
//
}
いくつかのテストメソッドだけでミドルウェアを無効にしたい場合は、withoutMiddleware
メソッドをテストメソッドの中で呼び出してください。If you would like to only disable
middleware for a few test methods, you may call the
withoutMiddleware
method from within
the test methods:
<?php
class ExampleTest extends TestCase
{
/**
* 基本的な機能テストの例
*
* @return void
*/
public function testBasicExample()
{
$this->withoutMiddleware();
$this->visit('/')
->see('Laravel 5');
}
}
カスタムHTTPリクエストCustom HTTP Requests
アプリケーションに対してカスタムHTTPリクエストを作成し、完全なIlluminate\Http\Response
オブジェクトを取得したい場合は、call
メソッドを使ってください。If you would like to make a
custom HTTP request into your application and get
the full Illuminate\Http\Response
object, you may use the call
method:
public function testApplication()
{
$response = $this->call('GET', '/');
$this->assertEquals(200, $response->status());
}
POST
やPUT
、PATCH
リクエストの場合、そのリクエストに入力データの配列を渡すことができます。もちろん、このデーターはRequestインスタンスを使用し、ルートやコントローラーで使用できます。If you are making
POST
, PUT
, or
PATCH
requests you may pass an array of
input data with the request. Of course, this data
will be available in your routes and controller via
the Request
instance[/docs/{{version}}/requests]:
$response = $this->call('POST', '/user', ['name' => 'Taylor']);
PHPUnitのアサートPHPUnit Assertions
PHPUnitテスト用に、数多くの追加アサートメソッドをLaravelは提供しています。Laravel provides several additional assertion methods for PHPUnit[https://phpunit.de/] tests:
メソッドMethod | 説明Description |
---|---|
->assertResponseOk(); ->assertResponseOk(); |
クライアントのレスポンスがOKのステータスコードを受け取ることを宣言Assert that the client response has an OK status code. |
->assertResponseStatus($code); ->assertResponseStatus($code); |
クライアントのレスポンスが指定したコードであることを宣言Assert that the client response has a given code. |
->assertViewHas($key, $value =
null); ->assertViewHas($key,
$value = null); |
レスポンスのビューに指定したデータが含まれていることを宣言Assert that the response view has a given piece of bound data. |
->assertViewHasAll(array
$bindings); ->assertViewHasAll(array
$bindings); |
ビューが指定したデータのリストを持っていることを宣言Assert that the view has a given list of bound data. |
->assertViewMissing($key); ->assertViewMissing($key); |
ビューが指定したデータを含んでいないことを宣言Assert that the response view is missing a piece of bound data. |
->assertRedirectedTo($uri, $with =
[]); ->assertRedirectedTo($uri,
$with = []); |
クライアントが指定したURIへリダイレクトすることを宣言Assert whether the client was redirected to a given URI. |
->assertRedirectedToRoute($name,
$parameters = [], $with =
[]); ->assertRedirectedToRoute($name,
$parameters = [], $with =
[]); |
クライアントが指定したルートへリダイレクトされることを宣言Assert whether the client was redirected to a given route. |
->assertRedirectedToAction($name,
$parameters = [], $with =
[]); ->assertRedirectedToAction($name,
$parameters = [], $with =
[]); |
クライアントが指定したアクションへリダイレクトすることを宣言Assert whether the client was redirected to a given action. |
->assertSessionHas($key, $value =
null); ->assertSessionHas($key,
$value = null); |
セッションが指定した値を持つことを宣言Assert that the session has a given value. |
->assertSessionHasAll(array
$bindings); ->assertSessionHasAll(array
$bindings); |
セッションが指定したリストを持つことを宣言Assert that the session has a given list of values. |
->assertSessionHasErrors($bindings
= [], $format = null); ->assertSessionHasErrors($bindings
= [], $format =
null); |
セッションにエラー情報があることを宣言Assert that the session has errors bound. |
->assertHasOldInput(); ->assertHasOldInput(); |
セッションが直前の入力を持つことを宣言Assert that the session has old input. |
->assertSessionMissing($key); ->assertSessionMissing($key); |
セッションが指定したキーを持っていないことを宣言Assert that the session is missing a given key. |
データベースとの関わりWorking With Databases
Laravelではさらに、データベースを駆動するアプリケーションのテストを簡単にできる多くの便利なツールを用意しています。その一つは指定した抽出条件に一致するデータがデータベース中に存在するかをアサートするseeInDatabase
ヘルパです。たとえばuser
テーブルの中にemail
フィールドがsally@example.com
の値のレコードが存在するかを確認したいとしましょう。次のようにテストできます。Laravel also provides a variety
of helpful tools to make it easier to test your
database driven applications. First, you may use the
seeInDatabase
helper to assert that
data exists in the database matching a given set of
criteria. For example, if we would like to verify
that there is a record in the users
table with the email
value of
sally@example.com
, we can do the
following:
public function testDatabase()
{
// アプリケーションを呼び出す…
$this->seeInDatabase('users', ['email' => 'sally@example.com']);
}
もちろん、seeInDatabase
メソッドやその他のヘルパは、利便性のために用意しています。PHPUnitの組み込みアサートメソッドを自分のテストに使用するのを制限するものではありません。Of course, the
seeInDatabase
method and other helpers
like it are for convenience. You are free to use any
of PHPUnit's built-in assertion methods to
supplement your tests.
テストごとのデータベースリセットResetting The Database After Each Test
直前のテストのデータが以降のテストに影響を与えないようにするために、それぞれのテストの後にデータベースをリセットできれば便利です。It is often useful to reset your database after each test so that data from a previous test does not interfere with subsequent tests.
マイグレーションの使用Using Migrations
一つの選択肢はそれぞれのテストの後にデータベースをロールバックし、次のテストの前にマイグレーションする方法です。Laravelはこれを自動的に処理するために、シンプルなDatabaseMigrations
トレイトを用意しています。テストクラスでこのトレイトを使用するだけです。One option is to rollback the
database after each test and migrate it before the
next test. Laravel provides a simple
DatabaseMigrations
trait that will
automatically handle this for you. Simply use the
trait on your test class:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
use DatabaseMigrations;
/**
* 基本的な機能テストの例
*
* @return void
*/
public function testBasicExample()
{
$this->visit('/')
->see('Laravel 5');
}
}
トランザクションの使用Using Transactions
もう一つの選択肢は、各テストケースをデータベーストランザクションでラップしてしまうことです。Laravelはこれを自動的に行うために便利なDatabaseTransactions
トレイトを用意してます。Another option is to wrap every
test case in a database transaction. Again, Laravel
provides a convenient
DatabaseTransactions
trait that will
automatically handle this:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
use DatabaseTransactions;
/**
* 基本的な機能テストの例
*
* @return void
*/
public function testBasicExample()
{
$this->visit('/')
->see('Laravel 5');
}
}
注意: このトレイトはデフォルトのデータベース接続をトランザクションでラップしているだけです。Note: This trait will only wrap the default database connection in a transaction.
モデルファクトリModel Factories
テスト実行前に何件かのレコードをデータベースに挿入する必要はよく起きます。こうしたテストデータを手動でそれぞれのカラムへ値を指定する代わりに、Laravelでは「ファクトリ」を使用しEloquentモデルの各属性にデフォルトを設定できます。手始めにアプリケーションのdatabase/factories/ModelFactory.php
ファイルを見てください。このファイルには最初からファクトリの定義が含まれています。When testing, it is common to
need to insert a few records into your database
before executing your test. Instead of manually
specifying the value of each column when you create
this test data, Laravel allows you to define a
default set of attributes for each of your
Eloquent models[/docs/{{version}}/eloquent]
using "factories". To get started, take a
look at the
database/factories/ModelFactory.php
file in your application. Out of the box, this file
contains one factory definition:
$factory->define(App\User::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'email' => $faker->email,
'password' => bcrypt(str_random(10)),
'remember_token' => str_random(10),
];
});
ファクトリで定義しているクロージャの中から、モデルの全属性に対するデフォルトのテスト値を返しています。このクロージャはFaker PHPライブラリーのインスタンスを受け取っており、これはテストのための多用なランダムデータを生成するのに便利です。Within the Closure, which serves as the factory definition, you may return the default test values of all attributes on the model. The Closure will receive an instance of the Faker[https://github.com/fzaninotto/Faker] PHP library, which allows you to conveniently generate various kinds of random data for testing.
もちろん追加のファクトリをModelFactory.php
に自由に追加できます。系統立てるためには各モデルのファクトリーファイルを追加したほうが良いでしょう。たとえば、database/factories
ディレクトリの中へUserFactory.php
とCommentFactory.php
ファイルを作成します。Of course, you are free to add
your own additional factories to the
ModelFactory.php
file. You may also
create additional factory files for each model for
better organization. For example, you could create
UserFactory.php
and
CommentFactory.php
files within your
database/factories
directory.
複数のファクトリタイプMultiple Factory Types
時々、同じEloquentモデルクラスに対し、複数のファクトリを持ちたいことがあります。たとえば、たぶん通常のユーザに加えて「管理者(administrator)」のためのファクトリも用意したいでしょう。defineAs
メソッドを使用すれば、そうしたファクトリを定義できます。Sometimes you may wish to have
multiple factories for the same Eloquent model
class. For example, perhaps you would like to have a
factory for "Administrator" users in
addition to normal users. You may define these
factories using the defineAs
method:
$factory->defineAs(App\User::class, 'admin', function ($faker) {
return [
'name' => $faker->name,
'email' => $faker->email,
'password' => str_random(10),
'remember_token' => str_random(10),
'admin' => true,
];
});
基本のユーザファクトリから全属性を複製する代わりに、属性を取得するraw
メソッドを使用できます。一度属性を取得したら、必要な追加の値を追加できます。Instead of duplicating all of the
attributes from your base user factory, you may use
the raw
method to retrieve the base
attributes. Once you have the attributes, simply
supplement them with any additional values you
require:
$factory->defineAs(App\User::class, 'admin', function ($faker) use ($factory) {
$user = $factory->raw(App\User::class);
return array_merge($user, ['admin' => true]);
});
テスト中のファクトリ使用Using Factories In Tests
ファクトリを定義し終えたら、テストかデータベースのシーディング(初期値設定)ファイルの中で、グローバルなfactory
関数を使用してモデルインスタンスを生成できます。では、モデル生成の例をいくつか見てみましょう。最初はmake
メソッドでモデルを生成し、データベースには保存しないでみましょう。Once you have defined your
factories, you may use them in your tests or
database seed files to generate model instances
using the global factory
function. So,
let's take a look at a few examples of creating
models. First, we'll use the make
method, which creates models but does not save them
to the database:
public function testDatabase()
{
$user = factory(App\User::class)->make();
// モデルをテストで使用…
}
モデルのデフォルト値をオーバーライドしたい場合は、make
メソッドに配列で値を渡してください。指定した値のみ置き換わり、残りの値はファクトリで指定したデフォルト値のまま残ります。If you would like to override
some of the default values of your models, you may
pass an array of values to the make
method. Only the specified values will be replaced
while the rest of the values remain set to their
default values as specified by the
factory:
$user = factory(App\User::class)->make([
'name' => 'Abigail',
]);
さらにモデルのコレクションや指定したタイプのモデルも生成できます。You may also create a Collection of many models or create models of a given type:
// App\Userインスタンスを3つ生成
$users = factory(App\User::class, 3)->make();
// App\Userの"admin"インスタンスを生成
$user = factory(App\User::class, 'admin')->make();
// App\Userの"admin"インスタンスを3つ生成
$users = factory(App\User::class, 'admin', 3)->make();
保存するファクトリモデルPersisting Factory Models
create
メソッドはモデルインスタンスを生成するだけでなく、Eloquentのsave
メソッドを使用しデータベースへ保存します。The create
method
not only creates the model instances, but also saves
them to the database using Eloquent's
save
method:
public function testDatabase()
{
$user = factory(App\User::class)->create();
// テスト中で生成したモデルを使用する…
}
ここでも、create
メソッドに配列で値を渡すことで、モデルの属性をオーバーライドできます。Again, you may override
attributes on the model by passing an array to the
create
method:
$user = factory(App\User::class)->create([
'name' => 'Abigail',
]);
モデルへのリレーション追加Adding Relations To Models
複数のモデルをデータベースへ保存することもできます。以下の例では、生成したモデルにリレーションを付けています。複数モデルの生成にcreate
メソッドを使用する場合、インスタンスのコレクションが返されます。そのため、コレクションで使用できるeach
などの便利な関数が利用できます。You may even persist multiple
models to the database. In this example, we'll even
attach a relation to the created models. When using
the create
method to create multiple
models, an Eloquent collection
instance[/docs/{{version}}/eloquent-collections]
is returned, allowing you to use any of the
convenient functions provided by the collection,
such as each
:
$users = factory(App\User::class, 3)
->create()
->each(function ($u) {
$u->posts()->save(factory(App\Post::class)->make());
});
リレーションと属性クロージャRelations & Attribute Closures
クロージャ属性をファクトリ定義の中で使い、モデルとのリレーションを追加することもできます。たとえば、Post
を作成する時に、新しいUser
インスタンスも作成したい場合は、以下のようになります。You may also attach relationships
to models using Closure attributes in your factory
definitions. For example, if you would like to
create a new User
instance when
creating a Post
, you may do the
following:
$factory->define(App\Post::class, function ($faker) {
return [
'title' => $faker->title,
'content' => $faker->paragraph,
'user_id' => function () {
return factory(App\User::class)->create()->id;
}
];
});
さらに、クロージャは評価済みのファクトリーの配列を受け取ることもできます。These Closures also receive the evaluated attribute array of the factory that contains them:
$factory->define(App\Post::class, function ($faker) {
return [
'title' => $faker->title,
'content' => $faker->paragraph,
'user_id' => function () {
return factory(App\User::class)->create()->id;
},
'user_type' => function (array $post) {
return App\User::find($post['user_id'])->type;
}
];
});
モックMocking
イベントのモックMocking Events
Laravelのイベントシステムを多用している場合、テスト中は静かにしてもらうか、特定のイベントモックしたいと思うでしょう。たとえばユーザ登録のテスト中は、たぶんUserRegistered
イベントのハンドラには全部起動してもらいたくないでしょう。起動されたら"Welcome"メールを送り…などされるでしょう。If you are making heavy use of
Laravel's event system, you may wish to silence or
mock certain events while testing. For example, if
you are testing user registration, you probably do
not want all of a UserRegistered
event's handlers firing, since these may send
"welcome" e-mails, etc.
Laravelはイベントハンドラを実行させずに期待するイベントが発行されたことを確認する、便利なexpectsEvents
メソッドを用意しています。Laravel provides a convenient
expectsEvents
method that verifies the
expected events are fired, but prevents any handlers
for those events from running:
<?php
class ExampleTest extends TestCase
{
public function testUserRegistration()
{
$this->expectsEvents(App\Events\UserRegistered::class);
// ユーザー登録コードのテスト…
}
}
指定したイベントが発行されないことを確認するには、doesntExpectEvents
メソッドを使います。You may use the
doesntExpectEvents
method to verify
that the given events are not
fired:
<?php
class ExampleTest extends TestCase
{
public function testPodcastPurchase()
{
$this->expectsEvents(App\Events\PodcastWasPurchased::class);
$this->doesntExpectEvents(App\Events\PaymentWasDeclined::class);
// ポッドキャスト購入コードのテスト…
}
}
全イベントハンドラの実行を停止したい場合は、withoutEvents
メソッドを使用してください。If you would like to prevent all
event handlers from running, you may use the
withoutEvents
method:
<?php
class ExampleTest extends TestCase
{
public function testUserRegistration()
{
$this->withoutEvents();
// ユーザー登録コードのテスト…
}
}
ジョブのモックMocking Jobs
場合によりアプリケーションへリクエストを作成し、コントローラーにより特定のジョブがディスパッチされることだけをテストしたい場合もあります。これにより、ジョブのロジックから切り離し、ルート/コントローラーを独立してテストできるようになります。もちろん、それからジョブ自身を別のテストクラスに分けてテストできます。Sometimes, you may wish to simply test that specific jobs are dispatched by your controllers when making requests to your application. This allows you to test your routes / controllers in isolation - set apart from your job's logic. Of course, you can then test the job itself in a separate test class.
Laravelは便利なexpectsJobs
メソッドを用意しており、期待しているジョブがディスパッチされたかを検査できます。しかしジョブ自身は実行されません。Laravel provides a convenient
expectsJobs
method that will verify
that the expected jobs are dispatched, but the job
itself will not be executed:
<?php
class ExampleTest extends TestCase
{
public function testPurchasePodcast()
{
$this->expectsJobs(App\Jobs\PurchasePodcast::class);
// ポッドキャスト購入コードのテスト…
}
}
注意: このメソッドは
DispatchesJobs
トレイトのdispatch
メソッドか、dispatch
ヘルパ関数により起動されたジョブだけを検知します。直接Queue::push
で送られたジョブは検知できません。Note: This method only detects jobs that are dispatched via theDispatchesJobs
trait's dispatch methods or thedispatch
helper function. It does not detect jobs that are sent directly toQueue::push
.
ファサードのモックMocking Facades
テスト時、頻繁にLaravelのファサードの呼び出しをモックしたくなります。たとえば以下のようなコントローラーアクションを考えてください。When testing, you may often want to mock a call to a Laravel facade[/docs/{{version}}/facades]. For example, consider the following controller action:
<?php
namespace App\Http\Controllers;
use Cache;
class UserController extends Controller
{
/**
* アプリケーションの全ユーザーリストの表示
*
* @return Response
*/
public function index()
{
$value = Cache::get('key');
//
}
}
shouldReceive
メソッドを使用し、Cache
ファサードへの呼び出しをモックできます。これはMockeryのモックインスタンスを返します。ファサードはLaravelのサービスコンテナにより管理され、依存解決されていますので、典型的な静的クラスよりもかなり高いテスタビリティーを持っています。例としてCache
ファサードへの呼び出しをモックしてみましょう。We can mock the call to the
Cache
facade by using the
shouldReceive
method, which will return
an instance of a
Mockery[https://github.com/padraic/mockery]
mock. Since facades are actually resolved and
managed by the Laravel service
container[/docs/{{version}}/container], they
have much more testability than a typical static
class. For example, let's mock our call to the
Cache
facade:
<?php
class FooTest extends TestCase
{
public function testGetIndex()
{
Cache::shouldReceive('get')
->once()
->with('key')
->andReturn('value');
$this->visit('/users')->see('value');
}
}
注意:
Request
ファサードはモックしてはいけません。テスト実行時にcall
とpost
のようなHTTPヘルパメソッドへ望みの入力を渡してください。Note: You should not mock theRequest
facade. Instead, pass the input you desire into the HTTP helper methods such ascall
andpost
when running your test.