WordPressで行う
継続的インテグレーション入門編
-私がプラグイン開発・保守地獄から学んだこと-
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 1
whoami
じこしょうかい
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 2
Toro_Unit
占部 紘 (うらべ ひろし)
長野県松本市在住
Frontend Engineer / Plugin Developer /
Web Designer
Github: @torounit
Twitter: @Toro_Unit
Facebook: fb.me/torounit
Blog: http://www.torounit.com
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 3
Profile
• 福島県郡山市生まれ。
• 群馬県太田市育ち。
• 長野県松本市9年目。
• にじゅうろくさい。
source:
https://commons.wikimedia.org/wiki/
File:Gunma-
NaganoPrefecturalRoad11202.jpg
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 4
WordPressとの関わり
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 5
WordPress 4.3 Core
Contributer
4.4でも引き続きコアコントリビューターの予定
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 6
Other Project
• Plugin Development
• WordCamp Kansai 2015 Speaker
Contribution
WP-CLI (v0.20.2) / VCCW / Some Plugin.
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 7
Plugins
• Custom Post Type Permalinks
• Simple Post Type Permalinks
• Powerful Posts Per Page
• RS CSV Importer Media Add-On
• etc...
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 8
Custom Post Type
Permalinks
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 9
主にこのプラグインの開発/保守の
経験から学んだことをお話しします。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 10
Custom Post Type Permalinks
• カスタム投稿タイプのパーマリンクを管理画面から設定でき
るようにするプラグイン。
• 2011.11.02リリース。ちょうど丸4年!
• Active install: 50,000+
• Downloads: 160,000+
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 11
実は、初めて作ったプラグイン。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 12
プラグイン界のシンデレラボーイ!!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 13
そんな4年前のToro_Unitは
どんなだったか
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 14
• ==と===の違い?
• Class?
• オブジェクト指向?
• デザインパターン?
• 副作用? 破壊的操作?
• interfaceって何のために存在してるの?
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 15
つまりコピペプログラマー
スパゲッティなクソコードを毎日生産する日々
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 16
WordPressとかそういうレベルの問題じゃ無い。
そもそもPHPのド基礎すらよくわかってない状態。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 17
要望と言う名のおしかりを受ける始末
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 18
デバッグモードで検証しろ!
Noticeでてる!
エスケープしろ!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 19
いろいろつらい!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 20
しかし
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 21
なぜか信じられないペースで
ダウンロード数が伸び始める
当時はWordPress3.2。たまたま時代の波に乗ってしまった。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 22
次々やってくるバグレポートと要望
今思えば地獄の始まり
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 23
• コメントのパーマリンクが動かない!
• 添付ファイルのURLがおかしい!
• カスタムタクソノミー使えるようにして!
• カテゴリーに対応させて!
• etc...
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 24
バグを直した!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 25
(`・ω・´) シャキーン
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 26
と思ったら
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 27
別のところがバグって動かない!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 28
Σ (゚Д゚;)
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 29
バグを直すとなぜかバグが増殖!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 30
機能を追加してももちろんバグる!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 31
まさに地獄!!!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 32
そんな私の昔の開発手法
1年半前くらいまで
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 33
1. コードを書く
2. パーマリンクを更新
3. ブラウザで何十ページのパターンにアクセスして確認
投稿ページ・アーカイブ・子ページ・コメントのパーマリン
ク・添付ファイル....etc.」x いろんな設定のカスタム投稿タイプ
とかタクソノミーとか...
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 34
開発時間の7割がブラウザでのテスト...
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 35
• そんなにまとまった開発の時間はとれない。
• やりかけで放置して寝るとだいたい解らなくなってる。
• 毎度毎度やってらんないので、たまにやると壊れてる。け
ど、原因不明。
• とりあえずロールバック。サヨナラしたコードは数知れず。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 36
リリース後にバグが見つかり徹夜で
バグフィックスすることも恒例行事
ごめんなさい。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 37
こんなのやってられるか!!!
いやほんとすみません
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 38
なんとかならんかね...
毎回ごめんなさいしながらアップデートするのつらい
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 39
さてどうしよう。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 40
ようやく本編
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 41
CI=継続的インテグレーションとは?
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 42
ソフトウェア作成時の品質改善や納期の短縮のための習慣のこと
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 43
具体的には...
• プログラムによるテスト
• テスト駆動開発
• テスト自動化
• 自動デプロイ / ビルド自動化
• etc...
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 44
プラグイン開発でやっていること
• ブラウザ上でのテストをやめてプログラムでテスト
• テスト駆動開発
• Travis-CIでテストを自動化
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 45
これで地獄からおさらばしました!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 46
1.WordPressでのテスト
コードの書き方
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 47
実例:カスタム投稿タイプの記事ペー
ジにアクセス出来ているかのテスト。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 48
ブラウザでテストしていたこと
1. 適当なカスタム投稿タイプを作成。
2. 投稿を作成。
3. アクセスして正しく投稿ページにアクセスできるかを確認。
(個別投稿ページにアクセスできているか、目的のページに到
達できているか)
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 49
これをテストコードにするとこうなる
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 50
class SampleTest extends WP_UnitTestCase {
public function test_permalink() {
register_post_type('hoge');
/*カスタム投稿タイプhogeの投稿を作成。*/
$args = array( 'post_type' => 'hoge' );
$id = $this->factory->post->create( $args );
/*WordPressを投稿にアクセスした状態に*/
$this->go_to( get_permalink( $id ) );
//is_single(), is_singular()のみがtrueなら合格。
$this->assertQueryTrue( 'is_singular', 'is_single' );
//生成した記事のIDと、URLから調べたIDが一致するかどうか
$post_id = url_to_postid( get_permalink( $id ) );
$this->assertEquals( $id, $post_id );
}
}
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 51
細かい解説は後ほどしますが、
基本的には、ブラウザでやっていたことを
そのままコードとして記述していくだけ。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 52
だまされたと思ってやってみると
そこまで難しくない!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 53
確認だけで一日仕事だったものが...
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 54
30秒足らずで終了!!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 55
革命起きた!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 56
ちょっとやってみたくなってきた?
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 57
じゃぁどうやってはじめればいいの?
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 58
1-1.PHPUnit & WP_UnitTestCaseを使う!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 59
PHPUnit
https://phpunit.de/
• PHPの定番テストフレームワーク。WordPressの本体も
PHPUnitでテストしてる。
• 日本語マニュアルが結構しっかりしてる。
https://phpunit.de/manual/3.7/ja/
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 60
アサーション
答え合わせメソッド。assertEquals($a, $b)だったら$aと$b
が一致したらOK、別のものならNG!とか。これがわかればテス
トがとりあえず書ける。
アノテーション
テストコードへのコメント。テストを分別したり、テストの環
境を設定したり出来る。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 61
この2つがわかればなんとかなる!
マニュアル見ればだいたい書いてある。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 62
テストの書き方の例
function add( $x, $y ) {
return $x + $y;
}
class SampleTest extends PHPUnit_Framework_TestCase {
public function test_add() {
$answer = add( 1, 2 );
$this->assertEquals( $answer, 3 );
}
}
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 63
WP_UnitTestCaseとは...
WordPressのコアで使われているテストコード。
PHPUnitにWordPress用の便利機能を多数搭載したもの。
• 記事・カテゴリー・ユーザー・マルチサイトのブログなどを
簡単に作れる!しかもダミーデータも突っ込んでくれる!
• WordPressの用のアサーション等もあって便利!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 64
さっきのテストコードをもう一度
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 65
class SampleTest extends WP_UnitTestCase {
public function test_permalink() {
register_post_type( 'hoge' );
/*カスタム投稿タイプhogeの投稿を作成。*/
$args = array( 'post_type' => 'hoge' );
$id = $this->factory->post->create( $args );
/*WordPressを投稿にアクセスした状態に*/
$this->go_to( get_permalink( $id ) );
//is_single(), is_singular()のみがtrueなら合格。
$this->assertQueryTrue( 'is_singular', 'is_single' );
//生成した記事のIDと、URLから調べたIDが一致するかどうか
$post_id = url_to_postid( get_permalink( $id ) );
$this->assertEquals( $id, $post_id );
}
}
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 66
例:ショートコードのテスト
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 67
ショートコードの仕様
• [greeting language="japanese"] で こんにちは と 表示
• [greeting language="english"] で hello と表示
http://www.slideshare.net/inc2734/word-campkansai2015-ci
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 68
class SampleTest extends WP_UnitTestCase {
public function test_languageがjapaneseならこんにちは() {
$greeting = do_shortcode( '[greeting language="japanese"]' );
$this->assertEquals( 'こんにちは', $greeting );
}
public function test_languageがenglishならhello() {
$greeting = do_shortcode( '[greeting language="english"]' );
$this->assertEquals( 'hello', $greeting );
}
}
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 69
意外に簡単!!!
ですよね...?
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 70
でも
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 71
PHPUnitの設定とかちょっとよくわからない。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 72
WP-CLI使え!!!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 73
WP-CLIでプラグインのひな形を作ると
$ wp scaffold plugin <プラグイン名>
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 74
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 75
テストに必要なものが準備済み!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 76
プラグインのディレクトリに移動して、
phpunitを実行するだけ。
$ cd ./wp-content/plugins/plugin-name/
$ phpunit //テスト実行!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 77
既存のプラグインにテストだけ生成も出来る!
$ wp scaffold plugin-tests <プラグイン名>
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 78
でも。。。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 79
• WP-CLIとかPHPUnitとかインストール面倒...
• ローカルでWordPressの動作環境も立てなきゃ...
• 特にWindowsだとだるい!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 80
VCCW使おう!!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 81
VCCW
• http://vccw.cc
• 宮内さんが開発してる Vagrant環境。立ち上げるだけで、
WordPressがインストール済みの仮想マシンが手に入る。最
近俺も巻き込まれた。
• WP-CLIもPHPUnitも全部入り!
• プラグイン開発に必要な環境がすべて手に入る!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 82
1-2.WordPressの本体のテストもよも
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 83
• 実際に動くものを読んでいくのが一番わかりやすい。
• 自分のプラグインの扱っている分野のテストコードは自分の
プラグインにも取り入れやすい。半分くらいパクってます。
• 一度やってみると、だんだん理解が深まってきて他のテスト
も読み書き出来るようになってくるよ!!!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 84
テストの書き方が何となく解ってくる
はず! いろいろ書いてみよう!
とりあえず自分の作ったプラグインとかにテストを足してみる
とか、簡単なプラグインを作ってみるとか。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 85
2.テスト駆動開発するべし
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 86
そもそもテストとは。
プログラムが正しい動作をするかどうか確認するためのもの。
言い換えると、プログラムが仕様に適合した動作を行うかどう
かのチェック。
ちゃんと書けば、生きた仕様書になる。
• 英語読めなくてもPHP読めれば仕様が解る!!!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 87
個人的な理解
• 仕様 = 問題文
• 実装 = 回答
• テスト = 答え合わせ
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 88
回答に合わせて問題文を
決めたらダメですよね。
あくまで理想論ですよ。理想論。(震え声)
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 89
テスト駆動開発をするメリット
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 90
• コードが変わってもテストが通れば、最低限の動作保証にな
る。
• テストを後付けすると、実装に合わせたテストを書きがち。
• ノリでコードを書き始めるより、ノリでテストを書く方が、
仕様が定まる。設計をしっかりやるようになる。自分のやり
たいこと、作りたいものがはっきり定まる。
• 仕様書を書くよりは、テストコードを書く方が絶対楽しい。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 91
3.テスト自動化するべし
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 92
ここまで散々テストやれとか言ってきたけど
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 93
毎度毎度実行するのがかったるい
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 94
めんどくさいものは大抵やり忘れる
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 95
自動化しよう!
• Githubで折角作ってるんだから、小幅な修正はブラウザから
やりたいときもある。
• Pull Request貰うのはとてもありがたいけど、いちいちクロ
ーンしてテストとかするのかったるい。
コミットを監視してテストを自動実行してくれる
サーバー(CIサーバー)欲しい!!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 96
Travis CIを使おう!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 97
Travis CIとは
• Gitのコミットを監視して、設定ファイル(.travis.yml)に書
かれている内容でテストやビルドやデプロイなどを実行でき
るWEBサービス。
• Githubとの連携が簡単! プルリクエストにも実行してくれる
しその結果もGithubの画面で見れる! しかもOSSならタダ!
• 類似サービスにCircle-CIってのもある。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 98
Travis CIでやるメリット
• WP-CLIで.travis.ymlのひな形も生成してくれる。
• 複数の環境でのテストが簡単に実行できる。WordPressの4.0
以降のバージョンでそれぞれPHP5.3以上の全てのバージョン
で実行とかやれる。
• HHVMも選択できる。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 99
まとめ
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 100
• WordPressのテストは、PHPUnitとWordPressのコアのテスト
ケースを使うのが便利。
• WP-CLIでひな形作ればだいたいOK.
• 環境構築面倒ならVCCW使っとけば良いよ!
• テスト駆動開発するべし!
• Travis CIはホントに便利!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 101
とりあえず、少しずつ始めてみよう。
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 102
拙くてもテストが無いよりはマシ!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 103
よりよい WordPress Lifeを!
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 104
参考資料
• WordPressで行う継続的インテグレーションのススメ
https://www.slideshare.net/horike37/wordpress-50908456
• WordCamp Kansai 2015 CI ハンズオン
http://www.slideshare.net/inc2734/word-campkansai2015-
ci
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 105
おわり
2015.10.31 @WordCamp Tokyo 2015 WordPressで行うCI入門編 106

WordPressで行う継続的インテグレーション入門編