狠狠撸

狠狠撸Share a Scribd company logo
Copyright ? Xchange Solutions All right reserved.
Fukuoka.php Vol.17 ~Rebooted~
尝补谤补惫别濒とテストについて
株式会社エクスチェンジ ソリューションズ
野田 健夫
2016.06.22
2
Copyright ? Xchange Solutions All right reserved.
こんにちは!
野田 健夫(のだたけお)
https://twitter.com/nodatakeo
https://www.facebook.com/nodatakeo
株式会社エクスチェンジ ソリューションズ
3
Copyright ? Xchange Solutions All right reserved.
今日の内容
1. 開発者に立ちはだかるテストの壁
2. なぜテストをやるのか?
3. テストの種類
4. テストへのジレンマ
5. Laravelテスト
? 環境構築
? API編
? ウェブページ編
? その他
6. まとめ
4
Copyright ? Xchange Solutions All right reserved.
開発者に立ちはだかるテストの壁
?環境作るのが面倒くさい。
?実装に比べて生産的でない感じがする。
?単体テストはともかくとして、シナリオ
テストが作りにくい。
?時間がない。
5
Copyright ? Xchange Solutions All right reserved.
なぜテストをやるのか?
?利用可能な状態を担保するため。
?要件を満たしているか確認するため。
?品質を高め、信頼性を上げるため。
システムが動かなかったり、品質が低いと
利用者?顧客の不利益になる。その
リカバリーにかかる作業コストも大きい。
6
Copyright ? Xchange Solutions All right reserved.
テストの種類
単体テスト
結合テスト
システムテスト
メソッド?関数の期待値検査
APIスキーマ?HTMLコンテンツチェック
シナリオテスト?脆弱性テスト
パフォーマンス、ログ、サーバー周りなど
これまでテスト自動化に悩んでいた領域
→xUnitテスト
→debugbar、slowログ、jmeter、zabbixなど
※ウェブアプリケーションでの例
7
Copyright ? Xchange Solutions All right reserved.
テストへのジレンマ
? テストの必要性は理解しているけど、コスト高い
のでは?
? 自動テストでできる検査って、ロジック以下の
assertHoge系の値検査ぐらいしかなかったっけ?
調べてみたらLaravelでいろいろテストを
支援する仕組みが用意されていた。
8
Copyright ? Xchange Solutions All right reserved.
Laravelのテスト: phpunit
?よく使われているphpunitでのテストを
ベースとしている。
composer dump-autoload
./vendor/phpunit/phpunit/phpunit tests
composer dump-autoload
./vendor/phpunit/phpunit/phpunit --filter 'testContent' tests/api/ApiContentControllerTest.php
./tests 以下のテストケースをすべて実行する。
./tests 以下のテストケースのうち特定のテストクラスでfilterして実行する。
9
Copyright ? Xchange Solutions All right reserved.
Laravelのテスト: 環境構築(Fixture)
? テストのフィクスチャ(Fixture:ベースとなるデー
タ設定)に Seederを使う。
過去の案件では、.envのAPP_ENVをみて、環境ごとに切り替えれるSeederを用意。
abstract class BaseSeeder extends Seeder
{
/**
* Get default seeds by table name
* @param $target table name
* @return void
*/
public function getConfig($target)
{
$config = require(base_path('database/seeds/default_'. config('app.env') . '.php'));
return array_get($config, $target);
}
}
class ContentSeeder extends BaseSeeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//削除
Content::truncate();
// コンテンツのデータ追加
foreach ($this->getConfig('contents') as $record) {
$dao = new Content ();
$dao->setUpRecord($record);
$dao->save();
}
}
}
テストの初期状態を共有
10
Copyright ? Xchange Solutions All right reserved.
Laravelのテスト: APIスキーマチェック
? seeJsonStructureメソッド
キー名の配列を渡して構造をチェック
? assertResponseStatus/assertResponseOkメソッド
HTTPステータスコードをチェック
// JSONパラメータ
$content = [];
// メソッド
$method = 'GET';
// URL
$url = route("contents.get");
// サーバー環境変数
$server = $this->getServerParameter($method, $url);
// JSONでAPIを呼び出し
$this->withServerVariables($server)
->json($method, $url, $content, $server);
// JSON構造のチェック
$this->seeJsonStructure([
'error',
‘content_list' => [
'*' => [
'id',
'title',
],
],
]);
// ステータスコードのチェック
$this->assertResponseStatus(200);
// レスポンス状態のチェック
$this->assertResponseOk();
11
Copyright ? Xchange Solutions All right reserved.
Laravelのテスト: API値チェック
? seeメソッド
レスポンス中に値が含まれるか検査が可能。
? responseプロパティ
レスポンス自体も取得できるので、値を抜き出せば、従来のassert
チェックも可能。
$this->see('Laravel 5');
$response = json_decode($this->response->content(), true);
$this->assertEquals('Laravel 5', $response['title']);
12
Copyright ? Xchange Solutions All right reserved.
Laravelのテスト: WEBコンテンツチェック
? visitメソッド
URLにアクセス。
? typeメソッド
指定IDフォームに入力。
? pressメソッド
指定IDボタンを押下。
? seePageIsメソッド
現在URL値をチェック。
$this->visit(route('admin.logout'));
$this->visit(route('admin.login'));
$this->type('a@aaa.com', 'login_id');
$this->type('testpw123', 'login_pw');
$this->press('action');
$this->seePageIs(route('admin.top'));
$this->see('TOPページ');
シナリオテストの動作チェックが可能。
13
Copyright ? Xchange Solutions All right reserved.
Chrome Extension: Laravel TestTools
14
Copyright ? Xchange Solutions All right reserved.
Chrome Extension: Laravel TestTools
開発ツール(ctrl+shift+i)のタブに「Laravel TestTools」が追加。
Selenium IDEの記録のような形で[Record]ボタンを押下すると
テストコードが生成されます。
15
Copyright ? Xchange Solutions All right reserved.
DB値のチェック
?seeInDatabaseメソッド
テーブル内に指定したキーのレコードがあるかチェック。
$this->seeInDatabase('users', ['email' => 'sally@example.com']);
16
Copyright ? Xchange Solutions All right reserved.
Test用Trait
? Illuminate/Foundation/Testing/DatabaseMigrations.php (Trait)
? テスト開始時にマイグレーションを実行し、終了後にマイグレーションロールバックする。
? Illuminate/Foundation/Testing/DatabaseTransactions.php (Trait)
? テスト開始時にトランザクションを開始し、終了後にロールバックする。
? Illuminate/Foundation/Testing/WithoutEvents.php (Trait)
? すべてのイベントを抑止して余計な処理を発生させない。
? Illuminate/Foundation/Testing/WithoutMiddleware.php (Trait)
? すべてのミドルウェアを抑止して余計な処理を発生させない。
? Illuminate/Foundation/Testing/Conserns/* (Trait)
? テスト向けの各種実装。see*系(seeJsonStructureなど)は、ほかのフレームワークでも参考になると
思います。
17
Copyright ? Xchange Solutions All right reserved.
まとめ
? テスト自動化は、テストの壁を低くする。
? 開発してリリースしておしまいでなく、開発が継続する案件
が増えている。デグレを避けるためにも必須になりつつある
ように感じている。
? フレームワークが持っているテストの仕組みを使うことでAPI
スキーマテストやシナリオテストといったより複雑なテスト
自動化をシンプルに行うことができる。
? テストは放っておくと腐る。テストが適切に行われるよう仕
様変更や動作が変わった場合は、メンテナンスを必ず行う。
18
Copyright ? Xchange Solutions All right reserved.
番外編:GuzzleでAPI/シナリオテスト
? GuzzleもAPIクライアントとしてだけでなく
テストにもシンプルで使い易いと思います。
public function __construct()
{
$this->endPoint = "https://hoge.jp";
$this->client = new HttpClient($this->endPoint);
}
/**
* OAuth 認証ページテスト
* @Test
*/
public function testAuthorization() {
$this->endPoint = “https://hogehoge.jp”;
$this->client = new HttpClient($this->endPoint);
// rfc6570
$uri = array(‘/auth/authorize?response_type={response_type}&client_id={client_id}&state={state}’,
array(‘response_type’ => ‘code’, ‘client_id’ => ‘demoapp’, ‘state’ => session_id()));
// リクエストを作成
$request = $this->client->get($uri);
// レスポンスを取得
$response = $request->send();
// 値検査
$this->assertEquals(200, $response->getStatusCode());
}
19
Copyright ? Xchange Solutions All right reserved.
番外編:テストを取り巻く技術要素
Behat/Mink/PHPSpec
PHPUnit
Framework Unit Testing
Library Unit Testing
単体テスト
結合テスト
Selenium
BDD
※どこまでテストケースに書くかは案件内容と設計内容による。

More Related Content

尝补谤补惫别濒とテストについて

  • 1. Copyright ? Xchange Solutions All right reserved. Fukuoka.php Vol.17 ~Rebooted~ 尝补谤补惫别濒とテストについて 株式会社エクスチェンジ ソリューションズ 野田 健夫 2016.06.22
  • 2. 2 Copyright ? Xchange Solutions All right reserved. こんにちは! 野田 健夫(のだたけお) https://twitter.com/nodatakeo https://www.facebook.com/nodatakeo 株式会社エクスチェンジ ソリューションズ
  • 3. 3 Copyright ? Xchange Solutions All right reserved. 今日の内容 1. 開発者に立ちはだかるテストの壁 2. なぜテストをやるのか? 3. テストの種類 4. テストへのジレンマ 5. Laravelテスト ? 環境構築 ? API編 ? ウェブページ編 ? その他 6. まとめ
  • 4. 4 Copyright ? Xchange Solutions All right reserved. 開発者に立ちはだかるテストの壁 ?環境作るのが面倒くさい。 ?実装に比べて生産的でない感じがする。 ?単体テストはともかくとして、シナリオ テストが作りにくい。 ?時間がない。
  • 5. 5 Copyright ? Xchange Solutions All right reserved. なぜテストをやるのか? ?利用可能な状態を担保するため。 ?要件を満たしているか確認するため。 ?品質を高め、信頼性を上げるため。 システムが動かなかったり、品質が低いと 利用者?顧客の不利益になる。その リカバリーにかかる作業コストも大きい。
  • 6. 6 Copyright ? Xchange Solutions All right reserved. テストの種類 単体テスト 結合テスト システムテスト メソッド?関数の期待値検査 APIスキーマ?HTMLコンテンツチェック シナリオテスト?脆弱性テスト パフォーマンス、ログ、サーバー周りなど これまでテスト自動化に悩んでいた領域 →xUnitテスト →debugbar、slowログ、jmeter、zabbixなど ※ウェブアプリケーションでの例
  • 7. 7 Copyright ? Xchange Solutions All right reserved. テストへのジレンマ ? テストの必要性は理解しているけど、コスト高い のでは? ? 自動テストでできる検査って、ロジック以下の assertHoge系の値検査ぐらいしかなかったっけ? 調べてみたらLaravelでいろいろテストを 支援する仕組みが用意されていた。
  • 8. 8 Copyright ? Xchange Solutions All right reserved. Laravelのテスト: phpunit ?よく使われているphpunitでのテストを ベースとしている。 composer dump-autoload ./vendor/phpunit/phpunit/phpunit tests composer dump-autoload ./vendor/phpunit/phpunit/phpunit --filter 'testContent' tests/api/ApiContentControllerTest.php ./tests 以下のテストケースをすべて実行する。 ./tests 以下のテストケースのうち特定のテストクラスでfilterして実行する。
  • 9. 9 Copyright ? Xchange Solutions All right reserved. Laravelのテスト: 環境構築(Fixture) ? テストのフィクスチャ(Fixture:ベースとなるデー タ設定)に Seederを使う。 過去の案件では、.envのAPP_ENVをみて、環境ごとに切り替えれるSeederを用意。 abstract class BaseSeeder extends Seeder { /** * Get default seeds by table name * @param $target table name * @return void */ public function getConfig($target) { $config = require(base_path('database/seeds/default_'. config('app.env') . '.php')); return array_get($config, $target); } } class ContentSeeder extends BaseSeeder { /** * Run the database seeds. * * @return void */ public function run() { //削除 Content::truncate(); // コンテンツのデータ追加 foreach ($this->getConfig('contents') as $record) { $dao = new Content (); $dao->setUpRecord($record); $dao->save(); } } } テストの初期状態を共有
  • 10. 10 Copyright ? Xchange Solutions All right reserved. Laravelのテスト: APIスキーマチェック ? seeJsonStructureメソッド キー名の配列を渡して構造をチェック ? assertResponseStatus/assertResponseOkメソッド HTTPステータスコードをチェック // JSONパラメータ $content = []; // メソッド $method = 'GET'; // URL $url = route("contents.get"); // サーバー環境変数 $server = $this->getServerParameter($method, $url); // JSONでAPIを呼び出し $this->withServerVariables($server) ->json($method, $url, $content, $server); // JSON構造のチェック $this->seeJsonStructure([ 'error', ‘content_list' => [ '*' => [ 'id', 'title', ], ], ]); // ステータスコードのチェック $this->assertResponseStatus(200); // レスポンス状態のチェック $this->assertResponseOk();
  • 11. 11 Copyright ? Xchange Solutions All right reserved. Laravelのテスト: API値チェック ? seeメソッド レスポンス中に値が含まれるか検査が可能。 ? responseプロパティ レスポンス自体も取得できるので、値を抜き出せば、従来のassert チェックも可能。 $this->see('Laravel 5'); $response = json_decode($this->response->content(), true); $this->assertEquals('Laravel 5', $response['title']);
  • 12. 12 Copyright ? Xchange Solutions All right reserved. Laravelのテスト: WEBコンテンツチェック ? visitメソッド URLにアクセス。 ? typeメソッド 指定IDフォームに入力。 ? pressメソッド 指定IDボタンを押下。 ? seePageIsメソッド 現在URL値をチェック。 $this->visit(route('admin.logout')); $this->visit(route('admin.login')); $this->type('a@aaa.com', 'login_id'); $this->type('testpw123', 'login_pw'); $this->press('action'); $this->seePageIs(route('admin.top')); $this->see('TOPページ'); シナリオテストの動作チェックが可能。
  • 13. 13 Copyright ? Xchange Solutions All right reserved. Chrome Extension: Laravel TestTools
  • 14. 14 Copyright ? Xchange Solutions All right reserved. Chrome Extension: Laravel TestTools 開発ツール(ctrl+shift+i)のタブに「Laravel TestTools」が追加。 Selenium IDEの記録のような形で[Record]ボタンを押下すると テストコードが生成されます。
  • 15. 15 Copyright ? Xchange Solutions All right reserved. DB値のチェック ?seeInDatabaseメソッド テーブル内に指定したキーのレコードがあるかチェック。 $this->seeInDatabase('users', ['email' => 'sally@example.com']);
  • 16. 16 Copyright ? Xchange Solutions All right reserved. Test用Trait ? Illuminate/Foundation/Testing/DatabaseMigrations.php (Trait) ? テスト開始時にマイグレーションを実行し、終了後にマイグレーションロールバックする。 ? Illuminate/Foundation/Testing/DatabaseTransactions.php (Trait) ? テスト開始時にトランザクションを開始し、終了後にロールバックする。 ? Illuminate/Foundation/Testing/WithoutEvents.php (Trait) ? すべてのイベントを抑止して余計な処理を発生させない。 ? Illuminate/Foundation/Testing/WithoutMiddleware.php (Trait) ? すべてのミドルウェアを抑止して余計な処理を発生させない。 ? Illuminate/Foundation/Testing/Conserns/* (Trait) ? テスト向けの各種実装。see*系(seeJsonStructureなど)は、ほかのフレームワークでも参考になると 思います。
  • 17. 17 Copyright ? Xchange Solutions All right reserved. まとめ ? テスト自動化は、テストの壁を低くする。 ? 開発してリリースしておしまいでなく、開発が継続する案件 が増えている。デグレを避けるためにも必須になりつつある ように感じている。 ? フレームワークが持っているテストの仕組みを使うことでAPI スキーマテストやシナリオテストといったより複雑なテスト 自動化をシンプルに行うことができる。 ? テストは放っておくと腐る。テストが適切に行われるよう仕 様変更や動作が変わった場合は、メンテナンスを必ず行う。
  • 18. 18 Copyright ? Xchange Solutions All right reserved. 番外編:GuzzleでAPI/シナリオテスト ? GuzzleもAPIクライアントとしてだけでなく テストにもシンプルで使い易いと思います。 public function __construct() { $this->endPoint = "https://hoge.jp"; $this->client = new HttpClient($this->endPoint); } /** * OAuth 認証ページテスト * @Test */ public function testAuthorization() { $this->endPoint = “https://hogehoge.jp”; $this->client = new HttpClient($this->endPoint); // rfc6570 $uri = array(‘/auth/authorize?response_type={response_type}&client_id={client_id}&state={state}’, array(‘response_type’ => ‘code’, ‘client_id’ => ‘demoapp’, ‘state’ => session_id())); // リクエストを作成 $request = $this->client->get($uri); // レスポンスを取得 $response = $request->send(); // 値検査 $this->assertEquals(200, $response->getStatusCode()); }
  • 19. 19 Copyright ? Xchange Solutions All right reserved. 番外編:テストを取り巻く技術要素 Behat/Mink/PHPSpec PHPUnit Framework Unit Testing Library Unit Testing 単体テスト 結合テスト Selenium BDD ※どこまでテストケースに書くかは案件内容と設計内容による。