Rails チュートリアルでモデル生成時に併せて erb ファイルが生成されない
Rails チュートリアルの下記あたりです。
第2章 Toyアプリケーション - Railsチュートリアル
以下のコマンドでモデルを生成しましょうというくだりがあるのですが、私の環境ではapp\views
以下に erb ファイルが生成されませんでした。
rails generate scaffold User name:string email:string
調べるとrails generate scaffold
コマンドではconfig\application.rb
を参照して生成をスキップするファイルを指定できるらしいので見てみました。
# Only loads a smaller set of middleware suitable for API only apps. # Middleware like session, flash, cookies can be added back manually. # Skip views, helpers and assets when generating a new resource. config.api_only = true
上記のような記述があったため、コメントアウトして再度rails generate scaffold
コマンドを実行したところ正常に生成されました。
今は SPA が普通になっているので標準で erb ファイルは作らないようになっているのでしょうか。
厳密に Rails チュートリアルと同じ Cloud9 環境ではなくて、コンテナ環境なのでインストールしてるライブラリなどに差異があるせいで初期設定が違うとか…?
Laravel は使っているので Laravel で言うとあれだな、というのはわかるのですが具体的な設定方法などはまだまだわからず手探りで進めています。
追記
config\application.rb
でconfig.api_only = true
が指定されるのは API モードでアプリケーションを新規作成した場合だそうです。
Rails による API 専用アプリケーション - Railsガイド
rails new my_api --api
上記のようにオプションを付けたときに API モードで作成されるそうです(つけた記憶はなかったんですが…)
【PHPUnit】php artisan test --parallel するときに設定ファイルを指定する
現在のプロジェクトでは CI でテストのジョブを分散させるために PHPUnit の設定ファイル(デフォルトだと phpunit.xml )が複数あります。
そのため、以下のようなことを同時にやりたい場合が発生します。
php artisan test --parallel
でテストを並列実行する(Laravel の artisan コマンドでテストを並列実行できるオプションがあります)- テストの設定ファイルを指定する
以下のようなコマンドになるかなと思って実行すると (--configuration
は設定ファイルを指定するオプション)
$ php artisan test --parallel --configuration ./phpunit-2.xml
怒られてしまいました…
... In CoverageMerger.php line 59: Coverage file /private/var/folders/tf/v66b2v0n7lv8gt8plbf7dnzc0000gn/T/CV_BOSyno is empty. No coverage driver found! Enable one of Xdebug, PHPDBG or PCOV for coverage.
エラーとしてカバレッジファイルがどうのこうのと怒られているのですが、今はテストさえ流せればいいのでオプションで除外します。
--parallel
オプションを付けると、実態はParatest
が実行されるようですので--no-coverage
でカバレッジを取得しないように指定してやると無事に実行できました。
php artisan test --parallel --configuration ./phpunit-3.xml --no-coverage
追記
設定ファイルphpunit.xml
に以下のような記述があるとカバレッジを出力しようとしてくれるようです。
これをコメントアウトすることでも--no-coverage
オプションは不要になりました。
<logging> <log type="coverage-html" target="./report" lowUpperBound="50" highLowerBound="80" /> </logging>
余談
設定ファイルを指定するオプションを調べていて気づいてしまったのですが、XML 設定ファイルで対象とするディレクトリをグループ分けができそうでした。
つまり、テスト実行時のオプションでそれぞれのグループを指定して実行という形にすれば CI でジョブも分けられて、ファイルはひとつにまとめるということができそう…!
xor 演算子の優先順位は = (代入)より下位
自戒を兼ねて記事にします。内容はタイトルの通りなんですが知らずハマりました……
結論
xor より代入のほうが優先順位が上なので $a に代入される値は xor が処理される前の値になります。
$a = true xor false; // true $a = false xor true; // false
そのため、意図した値を変数に格納するには括弧をつけて、代入より先に処理を実行させる必要があります。
$c = (false xor true); // true
&&
や||
と同じレベルだと思っていたのでまさか優先順位の問題だと思わずハマりました…
演算子の優先順位
ふと気づいて括弧つけたら意図した挙動になったのでドキュメントを確認したらその通りでした。
とりあえず以下のようにざっくり覚えておくことにしました。
&&
||
などの記号系=
代入and
or
xor
などの英字系
PHPUnit の setMethods の代わりに使うメソッド
概要
PHPUnit でモックを作成する際に、、モック対象となるメソッドを指定する際にsetMethods
を使っていると、これは現在非推奨とのことで代わりのメソッドを調べました。PHPStorm が教えてくれました… ありがとうございます🙏🏼
代わりのメソッド
setMethods
は今後削除されるので代わりには以下のどちらかを使うそうです。
onlyMethods
:すでに存在するメソッドをモックする場合addMethods
:まだ存在しないメソッドをモックする場合
どちらがよいのか
基本的にはonlyMethods
にしておくとモック対象のメソッドがなくなった場合は以下のようなエラー文と共にテストを失敗させてくれるのでテストは通ってるけどそのメソッド実は消されてた!みたいなことがなくて良さそうです。
Trying to set mock method "execute" with onlyMethods, but it does not exist in class "<モック対象のクラス名>". Use addMethods() for methods that do not exist in the class <テストのクラス名>
逆に存在するメソッドに対してaddMethods
を指定すると、それすでにあるからonlyMethods
を使ってや!とテストを失敗させてくれました。
テスト作成時に存在してなかったメソッドが後で作成された場合も気づけるようになっていて親切ですね。
参考
PHPUnit 9時代のTest Doubleの作り方 / deep dive into mockbuilder of phpunit 9 - Speaker Deck
【Laravel】assertDatabaseHas のテーブル名の取得をモデルから行ったほうが可読性が上がる気がする
テストで下記のようにデータベースの中身を確認するパターンよくあると思います。
$this->assertDatabaseHas( 'm_user', // テーブル名を文字列で指定 [ 'id' => $user->id, 'user_name' => $user->user_name, ]);
ただ、テーブル名を文字列で指定するのってなんか冗長だなぁと思っていました。
たまにモデル名と一致してなかったりするし、わざわざ Model のクラスまで見に行くのめんどくさいし…
そこで、以下のようにテーブル名をモデルから取得するように書いたほうがわかりやすいのではと。
$this->assertDatabaseHas( User::getModel()->getTable(), // テーブル名をモデルから取得 [ 'id' => $user->id, 'user_name' => $user->user_name, ]);
メリットとしては以下のようなものがあるかと思います。
デメリットとしては以下くらいかなと思います。
- テーブル名を取得する処理を挟んでるので処理負荷は(テーブル名直指定よりは)高い
- 記述が長くなる?
ただ、処理負荷としてはテスト用ファクトリでモデルつくるのと比べたら誤差なのでほぼこじつけみたいなものかなと思います。
【Laravel】CI での自動テストを並列化したらジョブの時間が短縮した
概要
CI での PHPUnit で行う自動テストで並列化オプションを有効にしたらテストが早く終わるようになりました。
ローカルではもちろん使っていたんですが CI でも有効したらいいじゃんと気づいたので有効しました。
並列化オプション
parallel
オプションでテストを並列化できます。内部的には Paratest を使っているようです。
php artisan test --parallel
ドキュメントにも書いてますね。
readouble.com
注意点というほどでもないのですが、PHPUnit のオプションを使う場合はparallel
オプションの後に付けないと怒られてしまいました。
artisan test
としてのオプションを先に受け取って、その後に PHPUnit のオプションという仕様のようです。
php artisan test --parallel --no-coverage -c ./phpunit.xml
並列数
並列数はprocesses
オプションで指定できますが、今回は特に指定しませんでした。
php artisan test --parallel --processes=4
デフォルトは使用できる論理コア数とのことでした。
GitHub - paratestphp/paratest: Parallel testing for PHPUnit
The default is auto, which means the number of logical CPU cores is set as number of processes.
他の処理はしておらず使用できるコアはできるだけ使ってほしいのでデフォルトです。
多すぎてもあんまり意味がないと思うのでとりあえず論理コア数で十分かと考えました。
あれ? CI サーバは他のジョブも並列で走るから全部使うのはあんまりよくないのかな…?
ここらへんは運用しながら調整かと思っています。
結果
CIサーバの混み具合にもよるのですがざっくり 5分 => 3分 くらいまでテストのジョブの時間が短縮できました。
ヤッター!
【Laravel】php artisan schema:dump でマイグレーションファイルを圧縮したらテストが早くなるか試してみた
結論
マイグレーションの圧縮をしても速度はほぼ変わりませんでした。
というかプロジェクトの CI 環境では遅くなりました…
もちろん、うちの環境では、という話なのでマイグレーションファイルの数や内容によっては早くなることも十分あると思います。
一例としてみていただければ…
やったこと
行ったのはphp artisan schema:dump
を実行して、マイグレーションファイルをひとつにまとめました。
このコマンドを実行するとdatabase
以下にschema
というディレクトリが作成されそこにダンプファイルが保存されます。
マイグレーションファイルがまとまるので、追加したけど後で消したカラムなどはそもそも作られなくなる(そのカラムに関する記述がなくなる)ようです。
(なので、そういう無駄な処理がなくなった結果早くなるかな~と思ったのでしたが誤差でした😂)
pg_restore コマンドが必要
テストを流す際に躓いた点でほぼメインです。
皆さんご存知の通りテスト前にはマイグレーションが走り、テーブルを新たに作り直します。
ただ、マイグレーションの圧縮を行った場合、ダンプファイルがまず読み込まれることになります。
このダンプファイルを読み込むために Laravel 内部ではpg_restore
コマンドが呼ばれます ※ PostgreSQL の場合
当然、テストに使用している PHP のイメージにはそんなコマンドは含まれていませんでした。
今回は速度の検証だけだったので、暫定でテストを実行するのと同じコンテナに無理やりインストールさせました。
どのみち追加の処理が発生してしまうというわけです…
気になったのがpg_restore
はartisan
コマンドから呼ばれてしまうので、PHP(というかLaravel)が動くコンテナにpg_restore
がインストールされている必要があるということです。
(ダンプを読み込むだけであれば別のコンテナを立ち上げてとかできると思うのですが)
なにか良い方法があるんでしょうか。
感想
CI はちょっとでも早くしたいです…!
テストは件数もあってかなり時間を食っているので特に早くしたい…!
とりあえず並列テストを設定しなかったことに今更気づいてしまったので来週は試してみたいと思います。