Posts for: #Testing

スマート縄跳びを購入

0時過ぎに寝て5時に起きて7時に起きた。CPAP 機器を装着する前に布団入ってだらだらしていたらそのまま寝てしまった。

今日の運動は腹筋ローラー,腕立て,スクワット,散歩をした。統計を 運動の記録 にまとめる。

スマート縄跳びを購入

縄跳びにもだいぶ慣れてきて数えながら跳ぶのも面倒になってきた。回数から時間に移行しようと考えているところ。検索したら普通にデータ連携できるスマート縄跳びがあることに気付いた。どの商品がよいのかよくわかっていないのでクラウドファンディングして有名そうな SmartRope LED Red を直販で購入した。

Subtotal ¥12,100
Shipping ¥1,900
Taxes ¥0
Total ¥14,000 JPY

海外から発送するなら2-4週間ぐらいはかかるかな?と予想していたら、そんなことはなくて韓国からの FedEx による発送で数日で届くみたい。

フロントエンドのテストフレームワーク

mswとstorybookで始めるフロントエンドテスト に参加した。そごうさんがハンズオンの講師を務められていた。

うちのチームはまだフロントエンドのテストを書いていない。まだまだ ui や機能を開発している段階なのでテストを書くのはもう少し先になる。一方で storybook はドキュメントの代替に導入していたので、その延長上にテストフレームワークがあるのはステップアップとしてよいように思えた。そごうさんの説明やハンズオンのサンプルもわかりやすかった。とてもよかったと思う。

日曜日に運動し過ぎて月曜から疲れている

1時半に寝て6時前に起きた。今日もよく眠れたと思う。1日中天気が悪かったのもあってあまり外出 (運動) せず休息の日になった。

今日の運動はレッグレイズ(椅子),腹筋ローラー,スクワット,散歩をした。統計を 運動の記録 にまとめる。

QA テスト

先週から引き続き、ずっとテストをしている。今日から windows server の active directory への連携に関するテストをしていた。プライマリグループという設定があって、その連携方法だけ分からなくてまた明日メンバーに教えてもらうことにした。テストは誰がやっても時間がかかるし、うまくいかないときに設定が悪いのか、データが誤っているのか、操作が適切ではないのか、調査にも時間がかかる。実際に手を動かしてみると、メンバーから聞いてるだけではわからない気付きも得られるのでこれはこれでよい経験になったと思う。ただ時間だけがどんどん削られるというのが欠点。

テックブログを読むためのイベント考察

テックブログ一気読み選手権20240219杯 に参加した。今日はにしはらさんが都合悪かったようで誰もいなかった。1人でテックブログを読んで、1人で hackmd にまとめて、それでイベントを終えた。その時間に都合が悪くても非同期に読めばよいというイベントの主旨ではあるけれど、なんのためにイベントをやっているのか?ということについて考えてみた。確かにイベントがあることでテックブログを1つ2つ読む機会になっている。これはイベントが中止であれば読まなかったかもしれない。一方で読んで他社へ話して共有する過程で新たな価値に気付くといったこともこのイベントの主旨ではあるのでその効果は落ちてしまう。なによりもイベントに参加して、誰もいなくて、ただまとめを書いて終えるというのはなにか寂しい。

テストと個人の気付き = issue

0時半に寝て4時に起きて5時過ぎに起きた。起きてからなにをしていたかあまり覚えてないが、気付いたら7時になってた。

今日の運動はレッグレイズ(椅子),腕立て,スクワット,背筋,散歩をした。統計を 運動の記録 にまとめる。

QA テスト

これまでは QA 期間中はメンバーに QA テストをお願いして、私は他のことをやっていることが多かった。今回は私も QA テストをやってみて、テストケースの内容の確認やテストをやってみての自分の感覚や所感などをみてみようと、泥臭くテストをコツコツやっている。テストをしていると、いろいろ気付くことがあって、メンバーにヒアリングしたり、issue 登録したり、なかなか思うようにはテストケースを消化できない。QA テストは担当者が重複してもよい。それは人によって視点が異なるから同じテストやっても異なる気付きがあったりする。今回の私はまさにそれで、私なりの気付きを issue 登録している。

同じことをやってもどれだけ issue 登録できるか、これが課題管理において大きな違いになる。アリエル時代でもテスターは issue 登録してなんぼなので本当に細かいことでも気付いたら issue 登録してくる。いくつかは invalid や duplicate で閉じるのだけど、そういう多くの issue の中から開発者も気付きを得ることもある。

街の歩き方

昨日と同じように、今日もホテルに戻ってきて筋トレしてから散歩に出掛ける。大きな公園や神社とかだと散歩しがいがあって楽しいけれど、大崎のような街中にはなさそう。それであちこち歩いていて気付いたのだけど、不動産会社の大きなビルの周りには公園ではないけれど、遊歩道のようなコースがいくつか設けられている。その道をぐるっとひと回りするのが楽しい。今日は 住友不動産大崎ガーデンタワー の周りの遊歩道をぐるっとまわってきた。

かがみの孤城

たまたまテレビをつけたら金曜ロードショーで かがみの孤城 をやっていた。みてたらおもしろかったらそのまま最後までみてしまった。鏡の世界に招かれた7人がリアルで会えないところは、なんとなくそうじゃないかと私が予想していたことがそのまま当たってた。誤った推理で並行世界じゃないかという問いかけが出てくる。その並行世界の概念図が私の解釈とは違っていて、その説明はこの物語の真相かどうかに関係なく、並行世界の概念とも違うんじゃないかと一人ツッコミしていた。d アニメストアならみていなかったかもしれないけど、テレビならストレッチしながらついついみてしまった。そういう視点ではテレビの価値は大きいのかもとも思えた。

寝台特急に初乗車

2時に寝て6時過ぎに起きた。本当はもっと早く寝た方がよいのに22時半から2時前まで作業してた。格闘家に学ぶ体脂肪コントロール 本に睡眠をとることや疲労を溜めないことが代謝をよくすると書いてあって、その通りだとは思うのだけど、なぜかここ最近は2時ぐらいまで作業していることが多い。いろいろうまくいかない。

今日の運動は腕立て,スクワット,背筋をした。統計を 運動の記録 にまとめる。

テスト環境の再構築

テスト環境の見直し の都築。先週末から cockpit 上の仮想マシンに OS をインストールしたりしていた。今日はテスト対象のアプリケーションをインストールして設定をしたり、既存のテスト環境を移行したりしていた。

いまテスト環境は1つしかないが、機能が増えてきて、複数の運用要件を満たす必要があって、1つの環境ですべてを検証するには不便な状態になっていた。そこで1つに全部入りするから相反する要件が競合するのであって、いまわかっている要件を用途別に、1つを3つの環境に分割した。1つしかないものを複数にすると、その重複するところのコストもかかる。その辺りの調整もしていた。テスト環境の構築について、過去に私が作ったものではあるけど、1回作って終わりだと思っていたのか、構築の issue にはなにか書いてあるかもしれないが、wiki には残していなかった。今回3つに作り直すにあたってドキュメントがあれば思い出したり、トライアンドエラーを行うコストも省略できて、ちゃんとドキュメントを書かないとあかんなと反省した。新規に設置した仮想マシンに openldap サーバーを構築する以外の作業は完了したはず。

サンライズ出雲の乗車と遅延

1ヶ月前に予約した 0時11分発の特急サンライズ出雲で東京へ向かう。

20時半にオフィスから家に帰ってきて、洗い物して、お風呂入って、ストレッチして、荷造りして、3時間もあれば余裕で出発できる。初めて寝台特急に乗る。間違いがないよう、改札で駅員に問い合わせる。すると、動物(シカ)と接触して列車が止まってしまっているという。再開予定ではあるが、駅員さんに話しかけた時点ではいつ再開するかはわかっておらず、その情報も乗客からオンラインでは調べられず、駅員さんしか状況を知る方法はないとのこと。動物とぶつかったぐらいで運休はないやろうという話しもあってそのままホームで待つことに。

ホームのアナウンスを聞いていると「運転しています。」と言い切るので再開したのかな?と期待するものの、35分遅れ→40分遅れ→45分遅れと遅延時間がどんどん増えていくので実際には停車していて点検中でも「運転している」とアナウンスするらしいということがわかった。最終的には80分遅れて三ノ宮に到着した。待合室で半分寝てたよ。そのまま目を覚さなくなるところでしたよ。

この時点で今日はゆっくり睡眠をとろうと思っていたのに大きな誤算だった。待ち疲れていたのもあったせいか、部屋に入って消灯してそのままわりとすぐに寝てしまった。列車に乗ったのが1時半、トイレに行って、駅員さんが切符確認に来て、2時頃には寝てしまったのではないかと思う。わりとよく眠れたと思う。列車の揺れと移動音は普通にはあるものの、私はこの手の環境には強いので、もちろん身体は疲労するかもしれないが、感覚的には気にせずそのまま寝ていたと思う。この状態で眠れるかどうかによって寝台特急の是非は変わってくるだろう。カプセルホテルよりは天井も高く、スペースも一回り広くて余裕がある。今回は下の真ん中ぐらいの部屋だったのだけど、場所によって揺れや移動音の聞こえ方も変わるという。通な人は部屋の位置もこだわるのかもしれない。

あと薄い毛布しかないため、冬はちょっと寒い。暖房入れて上着もかけてぎりぎりの暖かさかな。べつに眠れないほど寒いわけではないが、冬なんだからもう一枚布団を用意してくれてもいいのになという感覚はある。朝に起きて窓から線路は延々と眺められる。線路が好きな人にもよさそう。けっこうよかったのでまた来月も予約して寝台特急で出張へ行く。

QA のマイルストーンに入る

0時半に寝て4時頃に起きてそれからうたた寝して6時半に起きた。

今日の筋トレは腹筋:10x1,腕立て:15x1,スクワット15x2をした。

QA テストの段取り

今日から2週間 x 2 で QA テストをしていく。これまで余裕があったら手伝おうと思いつつ、なんやかんやインフラの作業やアプリケーションのリファクタリングやらをやっていて、QA テストはメンバーに任せて、私がやってみたことはなかった。今回は機能が増えてきて、物理的に検証の作業量も増えている。1人ですべてやるのはしんどいので役割分担をした方がよいだろうというので私も入ってやることにした。google sheets でカテゴリごとのテストケースをまとめている。そのシートごとに issue を作って担当者をアサインする。QA という観点からは同じテストを複数人で行うのは構わないので、issue も担当者ごとに同じものを複製してアサインすることにした。私もそうだけど、issue の担当者は1人の方が作業しやすい。メンバーからもそういう意見が出て、うちのチームに課題管理の考え方がかなり馴染んできたようにも思えた。

テスト環境を作り直す

21時頃から寝て何度か起きて7時半に起きた。昨日は頭が痛かったら早く帰って安静にしてた。安静にしたら直ったので大したことはなかったみたい。

今日の筋トレは腹筋:15x2,腕立て:10x1,スクワット15x2をした。

テスト環境の見直し

いまどきの開発の定番としては ci/cd でコミット単位にテスト環境にデプロイする仕組みを構築している。テスト環境は1つだけになるのだけど、プロダクトの開発を1年以上やってきて機能が増えたことによって、1つのテスト環境で相容れない複数の要件や機能を混在させることで管理や運用が煩雑になってきた。気付いたタイミングがよい時期だと思うのでこの機会に1つのテスト環境を3つのテスト環境に分散させようと思う。既存データを確認するだけなら1つでもよいが、id 連携という機能の特性上、複数のシステム間でデータ連携するため、システム間での依存関係が発生する。それを整理しないといけなくなったという次第。今日のところは現状把握や移行に必要な段取りなどを設計していた。

hugo のハンズオン資料作り

昨日の続き 。23時過ぎに外に出たついでにオフィスに寄り道して書き始めたらまた熱中してしまって2時ぐらいまで書いていた。ハンズオンで説明する内容は一通り書いたつもり。せっかくの機会だから上級者向けにもう少し知っていることを書いてみようとは思う。

頭痛でダウン

4時半に寝て7時半に起きた。深夜にハンズオン資料を作っていたらまた眠れなくなった。朝から頭痛くて調子が悪い。きっと生活のリズムが崩れているせい。早くお仕事を終えて帰って寝てた。

今日の筋トレは腕立て:10x1,スクワット15x1をした。

ldap エントリーの更新リクエストをランダムに行うツール

先週末から作っていたテストツールがようやく一通り動くようになった。ldap エントリーを生成したり、既存のエントリーに対して更新、削除、パスワード変更のリクエストをランダムに自動生成して送る。常時 id 連携の処理を動かしたときの並行処理の問題であったり、やや負荷をかけたときになにかの敷居値を超えて不具合がないかといった検証に使える。8月末に開発に着手して、年末から再開して、1月明けでようやく完成した。テストツールの開発の優先度が低いので後回し後回しにしているうちにどんどん後ろに流れていった。悪い開発の典型例。

hugo のハンズオン資料作り

昨日の続き 、、、をやろうと思っていたけど、頭痛でしんどかったので今日はお休み。イベントが公開された。

他のツールをみていて slate というツールは知らなかった。api ドキュメントを書くためのツールとある。

うちはいま redocly というツールを使って openapi のフォーマット (yml) で api ドキュメントを管理している。開発は openapi を使ってなくてドキュメントのためだけに openapi を使っている。量が増えてくると yml でドキュメントを書くのも辛くなってくるので markdown で api ドキュメントを書けるならそれもよいかもしれない。

結合テストのデバッグ

1時に寝て5時半に起きて7時半に起きた。なんか週の前半からバテている。

gitlab ci/cd の dind で mongodb のレプリカセット接続ができない

先日対応した mongodb のレプリカセット対応 で残った最後の課題。ローカルで実行すれば結合テストは動くが、gitlab ci/cd 環境では動作しないという問題が残っていた。gitlab-runner をローカルで実行できる ようにして、設定やパラメーターを変えたり、デバッグコードを埋め込んだり、コンテナに attach して振る舞いを確認したり、いろいろデバッグして原因はレプリカセット接続におけるホスト名の解決がコンテナ間でできていなかったことがわかった。

mongodb の結合テストは dockertest を使って実装している。これを gitlab ci/cd で動かすには dind を有効にする必要がある。dind 環境では2つのコンテナを使って結合テストが実行されるわけだが、テストが実行されるコンテナと mongodb コンテナが起動するコンテナの2つが生成される。このときにテストが実行されるコンテナから実際に mongodb が起動するコンテナのホスト名の解決と、mongodb が起動するコンテナ上での自分のホスト名の解決の2つが成立していないとレプリカセット接続ができない。要は1台のローカルホスト上で結合テストを実行するのと、2つのコンテナ上で実行されるのでは設定を変更する必要があるということに気付いた。

具体的には dockertest の次のパラメーターを、実行環境から解決するホスト名を考慮して設定すればよいと気付いた。

pool.RunWithOptions(&dockertest.RunOptions{
    ... 
    Hostname:   executor,
    Env: []string{
        ...
        fmt.Sprintf("MONGODB_ADVERTISED_HOSTNAME=%s", executor),
        ...
    }
})

たったこれだけの修正だし、現状の動作の振る舞いが分かればすぐに直せるものではあるけれど、このデバッグにはまた2-3時間を費やした。mongodb のレプリカセット接続はなかなか大変。

mongodb のレプリカセットのデプロイ調査

4時前に寝て6時半に起きた。1時過ぎまで作業して、帰って少しゲームして、うまく眠れなくてだらだらしていた。

mongodb のレプリカセットの調査

以前 mongodb でトランザクションを使うときにレプリカセットが必要 なことがわかった。他機能の開発途中だったので一旦後回しにしていたものを回収している。状況によってはメンバーに委譲してもよかったんだけど、私が遊撃で出張ってみることにした。実際に調べてみてコンテナの運用も考慮するとけっこう難しいことがわかってきた。

mongosh からは Replication Methods を使ってレプリカセットの操作ができる。これはユーティリティのようなもので mongodb としての低レベルのコマンド操作は Replication Commands になる。mongo-go-driver はレプリカセット向けのユーティリティを提供していないため、Replication Commands を RunCommand() の低レベル API を使って自分で実装しないといけない。

例えば、レプリカセットの初期化をするときは次のように replSetInitiate というコマンドを適切なパラメーターで呼び出す。あまりドキュメントで丁寧に説明されていないので試行錯誤でエラーメッセージをみながら実装することになる。とくにはまるのが mongod のサーバーは --replSet myrs のようにレプリカセットを指定して起動させるものの、初期化コマンドを実行するときはまだレプリカセットを設定していないため、レプリカセットを指定せず、且つ direct パラメーターをセットしないと mongod サーバーに接続できない。この微妙な設定を把握するのにはまった。これが正しい手順かどうかもわからないが、ググったりしているとフォーラムでそういったコメントが散見されたりする。おそらく mongosh の Replication Methods を使うと、クライアントからサーバー接続は裏方でよしなにやってくれるのでそっちの方が簡単ではある。

func (r *ReplicaSet) Initiate(ctx context.Context, config bson.M) error {
	client, err := r.connectDirect(ctx)
	if err != nil {
		return fmt.Errorf("failed to connect with direct: %w", err)
	}
	defer client.Disconnect(ctx)

	var result bson.M
	cmd := bson.D{{Key: "replSetInitiate", Value: config}}
	if err := client.Database(r.db).RunCommand(ctx, cmd).Decode(&result); err != nil {
		return fmt.Errorf("failed to run replSetInitiate(): %w", err)
	}
	log.PrettyPrint("completed to initiate", result)
	return nil
}

func (r *ReplicaSet) connectDirect(ctx context.Context) (*mongo.Client, error) {
	opts := options.Client().
		SetAuth(options.Credential{
			Username: r.config.User,
			Password: r.config.Passwd.String(),
		}).
		SetHosts(r.config.Hosts).
		SetDirect(true) // must be true
	return mongo.Connect(ctx, opts)
}

func InitSingleReplicaSet(
	ctx context.Context, cfg *config.MongoDB,
) error {
	rs := NewReplicaSet(cfg)
	initConfig := bson.M{
		"_id": cfg.ReplicaSet,
		"members": []bson.M{
			{"_id": 0, "host": "localhost:27017"},
		},
	}
	return rs.Initiate(ctx, initConfig)
}

さらに mongod サーバーを起動するときに --replSet--keyFile (認証が必要な場合のみ?) という2つのパラメーターを指定する必要がある。--replSet はレプリカセットの識別子を指定する。そして --keyFile は共通鍵を指定する。この共通鍵を生成するには次のようにする。

$ openssl rand -base64 756 > my-mongo-keyfile
$ chown mongodb:mongodb my-mongo-keyfile
$ chmod 400 my-mongo-keyfile

普通のサーバーインスタンスならすぐできることだが、コンテナの運用において面倒なのが owner とパーミッションを設定しないといけないところ。mongo のコンテナは mongodb ユーザーで起動するため、root でマウントされたファイルシステムには書き込みできなかったりして keyFile の配置をどう扱えばよいのかが難しい。docker hub の mongo の issues でもどうやって設定したらいいの?って議論が発散している。mongo 本体が公式のスクリプトや仕組みを提供していれば済む話しだけど、どうもそうではないみたい。だから泥臭い方法で自分でなんとかしないといけないようにみえる。

dockertest でもレプリカセットの設定について次の issue として登録されている。mongo のコンテナを使ったテストの場合、dockertest のレイヤーが挟まるのでさらにわかりにくくなっている。テストを動かすためにどういった設定が必要かは把握できたのでなにかよい方法を考えてコントリビュートしたい。

メールの結合テストのツール

0時に寝て4時と5時に起きて6時に起きた。最近は4時から1時間ごとに起きたりする。メールの送信処理のリファクタリングのコードレビューが長く続いていてなかなかややこしい。

mailhog の web api を使って検索する

メール送信の結合テストに mailhog というツールを使っている。smtp サーバーとしてメールを受け付けて web ui でそのメールの内容を確認できる機能をもっている。さらに web api で任意のメール取り出すこともできる。パスワードリセットの一時トークンをメールで送信するため、結合テストで一連のパスワードリセットを検証するにはメールから一時トークンを取り出さないといけない。そこで mailhog の出番だ。

検索 api を使うと任意のメールをフィルターできる。例えば、送り先のメールアドレスで検索するときは次のようにリクエストする。

$ curl -s "http://localhost:8025/api/v2/search?kind=to&query=myuser1@example.com" | jq .

うちらのやり方はメールのメッセージ ID に意図した uuid をセットしている。メールのメッセージから指定した uuid を含んでいるかを検索することで任意のメールをフィルターできる。

$ curl -s "http://localhost:8025/api/v2/search?kind=containing&query=28c9391f-25a5-4a8f-9035-7b8d5ac2d0f4" | jq .

それを結合テストのテストコードから呼び出すようにユーティリティを作ると次のようなコードになる。

import (
	"github.com/mailhog/data"
)

type mmSearchResult struct {
	Total int            `json:"total"`
	Count int            `json:"count"`
	Start int            `json:"start"`
	Items []data.Message `json:"items"`
}

func searchMail(
	host string, kind string, query string,
) (*mmSearchResult, error) {
	q := url.Values{}
	q.Set("kind", kind)
	q.Set("query", query)
	u := &url.URL{
		Scheme:   "http",
		Host:     host,
		Path:     "/api/v2/search",
		RawQuery: q.Encode(),
	}
	url := u.String()
	slog.Debug("mailhog search endpoint", "url", url)

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, fmt.Errorf("http create new request error. err: %s", err)
	}
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("http request error. err: %s", err)
	}
	if res.StatusCode >= 400 {
		return nil, fmt.Errorf("returned response code is %d", res.StatusCode)
	}
	var r mmSearchResult
	if err := convertBody(res, &r); err != nil {
		return nil, fmt.Errorf("failed to convert: %s", err)
	}
	return &r, nil
}

歯医者

17時から歯科検診へ行ってきた。歯科検診をしてくれた今回のスタッフはおそらく初めてだったと思うが、手際がよくていつもよりもストレスが少なかった気がした。うちのチームのメンバーは朝方なので8時過ぎにはだいたいみんな始業し始める。なので、朝よりも夜にいない方がメンバーにとってよいだろうと考えて、朝一 (9時) に歯医者へ行くよりも最終 (17時) に行くようにしている。

pycamp ふりかえり

先週末の Python Boot Camp のふりかえり。ここまでがスタッフのお仕事なので一般的な kpt でイベントのふりかえりをした。仕事じゃないし、大きなトラブルもなかったし、参加者の評判 (アンケートの内容) もよかったので概ねよい内容だったと思う。テキストの改善点は直接 issue に追加してほしいと言われたので報告した。是非も含めてスタッフに判断してほしいので私が直すつもりはない。

パスワードリセットのテストのためのガイドライン

0時に寝て何度か起きて4時に起きて仮眠して6時に起きた。あまり寝た気がしない。

OWASP のパスワードリセットのガイドライン

パスワードリセットの仕組みをメンバーに開発してもらっている。そのコードレビューが先週から白熱している。セキュリティが関連するので堅牢に作る必要があるのでここはあまり妥協せきない。お手伝い先のシニアエンジニアから独自設計で作るのではなく、最低限、世の中の一般的なガイドラインに従っているかを確認するために OWASP のガイドラインを紹介してくれた。これはパスワードリセットの仕組みをテストするための要項をあげている。

これをメンバーに読んでもらって理解して実装しろと言いたいところでもあるが、私自身、読んだことがないとレビューできないことに気付いて、これは私が読んだ上で既存の設計や実装を見直すべきだと判断して deepl を駆使しながらほとんどを読んでみた。たしかに読んでみていくつか抜け・漏れに気付いたり、うちのセキュリティポリシーとして意図的に緩和しているところも認識できたりして、結論から言って読んでよかったと思う。当初はパスワードリセットのために一時トークンを1つだけ使っていたのだけど、それも2つを別々の経路に送って、割符のように組み合わせて認証する仕組みに変更した。よりセキュアにするという意図では一時トークンも1つよりも2つの方がよいというのは概ね正しいと思う。