Top page  1/41
25
2019

AngularのE2EテストでChromeDriverのバージョンを固定する方法

CATEGORYJavaScript
最近のAngualr (Angular CLI) だと、Protractorを使ったE2Eテストが自動でセットアップされるんだけど、ちょっと前にドライバとブラウザのバージョン不一致で動かなくなってしまったのでその対策をまとめとく。

E2Eテストでは protractor.conf.js に定義されたブラウザが使われる。が、ブラウザそのものは、実行環境に別途自分でインストールする必要がある。なので、普通にアップデートしてるとちょくちょくバージョンが上がる。
ng e2e コマンドでは、テスト前に勝手に webdriver-manager update というコマンドを流してドライバをバージョンアップして追従してくれるので、通常は問題ない。
ところが、何かの拍子に両者のバージョンがずれると、途端にE2Eテストが動かなくなってしまう。
(特にChrome系の場合、ドライバがChromeに合わせて新しくなる一方、CentOS版Chromiumとかは更新が遅くてバージョンがずれる。)

最終的に見つけたのが、以下のようにnpm script内でオプションを指定して自動更新を止め、pree2eとして前処理で指定したバージョンのドライバをインストールさせる手段だった(以下、package.jsonから抜粋)。
"pree2e": "webdriver-manager update --versions.chrome=77.0.3865.40",
"e2e": "ng e2e --webdriver-update=false",
※ 指定するのはブラウザではなくドライバのバージョン。Chromeの場合はChromeDriver

ブラウザを更新するとき、ここも更新しないといけないという手間はあるものの、これでテストを安定させることができた。参考までに。

Tag: Angular

21
2019

関数名でよく使う英単語とニュアンス

CATEGORY開発全般
最近またコードレビューでGetXxxと言いながら更新してる関数を見かけたのでorz、何番煎じか分からないけど、関数名(メソッド名)によく使う英単語とそのニュアンスをまとめてみる。
なお、以下は俺の感覚なので、人によって違うというのはもちろんあると思うし、またフレームワーク等で命名規則が定まっている場合はそちらが優先なので、念のため。

Get
データを取得する。かなり汎用な語句で、データ取得全般に用いられる。オブジェクトのプロパティを取得するgetterのイメージも強い。そのためか、処理にコストがかからず、またデータを書き換えるといった副作用が無いイメージが強い。

データ取得ではあるが、上記の理由からDB検索などではGetを用いることは少ない(代わりにFind等を使う)。一方で、Key-Valueストアへの参照ではGetが使われることも多い。また、動的に戻り値を生成するような処理に使われることもあるが、こちらは別の単語(Make等)で区別するケースも多い。

英単語としての "get" は幅広い意味を持つが、プログラム上では上記のイメージが極めて強いため、データ取得以外の意味で用いてはならない
Set
データを設定する。Getの対になる単語だが、こちらはそこまで汎用的には用いられない。プロパティを設定するsetterや、また何かフラグを立てたりといった用途のイメージ。

データ設定であるが、同じくDB更新には用いられない(ただしDBにフラグを立てるなどはありえる)。一方でこちらもKey-Valueストアへの保存では用いられることも多い。
Is
bool値を返す処理。これもかなり汎用な語句で、単にgetterのbool版として用いられることもあれば、最終的にbool値を返す大きな関数に使われていることもある。副作用は無いイメージ。

なお、Isは英語の疑問文由来なので、前後の文脈によってはIs以外になるケースもある筈だが、日本人にはよく分からないのでたいてい全部Isになる。

Tag: プログラミング

18
2019

Laravel 6.0.3 で Call to undefined method setFormatter() のエラー

CATEGORYPHP
2019/10/4追記、Issue送ったらLaravel 6.1.0で修正されました。バージョンアップでOKです(^-^)

今月頭に新しい長期サポート版 (LTS) となるLaravel 6.0がリリースされたわけだが、やったー!LTSだー!と飛びついたら一個だけバグっぽい現象に遭遇したので対処法書いとく。発生したのはバージョン6.0.3。

現象としては、Laravel 6.0にアップグレードした後に、次のような例外が発生するというもの(以下エラーログから抜粋)。
[2019-09-18 09:59:05] laravel.EMERGENCY: Unable to create configured logger. Using emergency logger. {"exception":"[object] (Error(code: 0): Call to undefined method Monolog\\Handler\\NullHandler::setFormatter() at /vagrant/server/vendor/laravel/framework/src/Illuminate/Log/LogManager.php:376)
[stacktrace]
#0 /vagrant/server/vendor/laravel/framework/src/Illuminate/Log/LogManager.php(347): Illuminate\\Log\\LogManager->prepareHandler(Object(Monolog\\Handler\\NullHandler), Array)
#1 /vagrant/server/vendor/laravel/framework/src/Illuminate/Log/LogManager.php(185): Illuminate\\Log\\LogManager->createMonologDriver(Array)
エラーになっているのはMonologNullHandlerで、確かに自分の環境では、config/logging.php でこんな感じにMonologハンドラチャンネルを設定していた。
'fluent' => [
'driver' => 'monolog',
'level' => 'info',
'handler' => env('FLUENTD_ENABLE', true) ? App\Logging\FluentdHandler::class : Monolog\Handler\NullHandler::class,
],
しかし5.8の時は動いていたのに何故?と思いLogManagerを見てみたところ、Laravel 5.8→6.0でMonolog 2.0が入ってくるようになった結果バグったようだ。
具体的には、Monolog 1.xの頃はHandlerInterfaceにsetFormatter()があったのだが、2.0ではそれがFormattableHandlerInterfaceに分離されたようで、後者を継承していないハンドラーを使うとエラーになってしまう様子。
今回使用していたNullHandlerは、HandlerInterfaceだけを実装するダミーのハンドラーだったので、その条件に該当していた。

Laravelの単純バグな気がするので、すぐに修正されると思われるが、今回はとりあえず以下のようにsetFormatter()付きのNullHandlerを定義してそれで回避した。
namespace App\Logging;

use Monolog\Handler\FormattableHandlerInterface;
use Monolog\Handler\FormattableHandlerTrait;
use Monolog\Handler\NullHandler as NullHandlerBase;

class NullHandler extends NullHandlerBase implements FormattableHandlerInterface
{
use FormattableHandlerTrait;
}
上記以外は今のところこれといった問題も無く、各種ライブラリの対応も進んできたので、無事6.0に移行できそうである。
5.5も5.8も来年にはサポートが終わってしまうため、以降する方はお早めに。

Tag: PHP Laravel

07
2019

ASP.NET CoreでAPIテスト (統合テスト) を行う

CATEGORY.NET
またASP.NET Coreネタ。今度はASP.NET Coreの自動テストで、APIレベルのテスト (統合テスト, Integration tests) を行う方法について。バージョンは引き続き2.1。

統合テストの方法については、公式ドキュメントにも以下のように説明がある。
が、いろいろ説明が冗長だったり、かと思えば足りなかったりと、最初にこれだけ見ても正直分かり辛い。
なので、実際に統合テストを行うのに必要な要点とかをまとめてみる。
(最終的なテストの実装例はこちら参照。)

テストプロジェクトの作成

まずテストプロジェクトの作成。Visual Studioで、公式のサンプルに合わせてxUnit.netのテストプロジェクトを作る。
(ただし、統合テストの仕組み自体はテストライブラリによらず共通と思われる。)

作成したプロジェクトでは、csprojファイルの冒頭を <Project Sdk="Microsoft.NET.Sdk.Web"> に差し替え、かつNuGetなりで以下のライブラリを参照している状態にする。
あと当然テスト対象のプロジェクトも参照する。
ここまでは普通のテストプロジェクトを作る場合とほぼ同じだと思う。

WebApplicationFactoryによるAPIテスト例

ASP.NET Coreの統合テストには、2.1から WebApplicationFactory というクラスが用意されている。
これにジェネリックでテスト対象プロジェクトの Startup クラスを指定すると、そのStartupを使ってテスト用のサーバーが立ち上がり、そこにリクエストを投げられるようになる。
単にAPIを呼ぶだけで良いのであれば、これを直接そのまま使うこともできる。

Tag: ASP.NET .NET

03
2019

Serilogでログを種類ごとに別のファイルに出力する

CATEGORY.NET
ASP.NET Coreネタ。ASP.NET Coreでは標準のロガーがあるが、そのままだとファイル出力ができないらしく、別途ライブラリを組み合わせるのが定番らしい(?)。
で、有名どころの「Serilog」を使ったのだが、ログを種類別に違うファイルに出力しようとしたら、ちょっと手間取ったので方法を書いておく。例によってStack Overflow等を参考にした。
最初に出来上がった設定を書いてしまうと、こんな感じ(使用例はこちら)。
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Logger",
"Args": {
"configureLogger": {
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "/var/log/local/aspnetcoreapi-example/app.log",
"rollingInterval": "Day"
}
}
],
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "SourceContext = 'Honememo.AspNetCoreApiExample.Middlewares.AccessLogMiddleware' or StartsWith(SourceContext, 'Microsoft.EntityFrameworkCore.')"
}
}
]
}
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "/var/log/local/aspnetcoreapi-example/access.log",
"rollingInterval": "Day"
}
}
],
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "SourceContext = 'Honememo.AspNetCoreApiExample.Middlewares.AccessLogMiddleware'"
}
}
]
}
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "/var/log/local/aspnetcoreapi-example/sql.log",
"rollingInterval": "Day"
}
}
],
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "StartsWith(SourceContext, 'Microsoft.EntityFrameworkCore.')"
}
}
]
}
}
},
{
"Name": "Debug"
}
]
}
}
appsettings.json による設定。コードで設定する場合は同名のメソッドなどに読み替えてください。

ASP.NET Coreではロガー使用時に呼び出し元クラスを紐づけるものらしい(?)ので、そのクラス名でフィルタリングを行い、フィルタリングした結果をそれぞれのログファイルに出力している。
上の例では、AccessLogMiddleware のログを access.log ファイルに、EntityFrameworkCoreが出力するSQLログなどを sql.log ファイルに、それらを除外した残るログを app.log ファイルに出力している。
設定の構造的には、外側のロガーの設定の中に、Include/Excludeの設定をしたサブロガーがある形となっている。

クラスで分けられないケースは条件をもっと工夫する必要がありそうだけど、とりあえずこういう形で出力先を分けられますということで。

Tag: ASP.NET .NET