Posts for: #Testing

イレギュラーな出張

本当は昨日の夜にもう少し開発しようと思っていたが、体力的に衰えているせいか、晩ご飯食べに帰ってそのまま家でだらだらしていた。翌1-3時前までオフィス戻って作業して、それから出張の準備をして、5時過ぎからいつも通り始発の新幹線に向かった。

定例会議

私のリファクタリング issue が1つだけ未達で残ってしまった。他の新機能開発はほぼ予定通り完了できた。メンバーががんばってお仕事してくれたことに感謝。無理なスケジュールを強いていないというのもあるが、ちゃんと見積もりと工数を管理できていることそのものはよいことだと思う。概ね予定通りであることを確認して、あと2つのマイルストーン (1ヶ月) を使って qa テストにあてる。これも web 開発からしたら驚くほどの工数を使っているようにみえると思う。しかし、品質の悪い web 開発を私はたくさんみてきたので結果的に qa をちゃんとやる方が工数削減になると私は考えている。

いま作っているプロダクトのライセンスが実は Apache License v2 になる。oss な会社だから基本的にプロダクトは oss なライセンスで提供しているらしい。とはいえ、リポジトリを一般公開しているというわけでもないため、広く oss として使ってもらいたいというほどのモチベーションでもない。お客さんが要求すればソースコードも提供するといったスタンスらしい。実際にお客さんがソースコードを要求してくることは皆無らしいが。

もうやんカレー

過去に虎ノ門で働いた頃、もうやんカレー好きな同僚がいて懐かしくて 新橋店 へ行ってみた。私がこのお店へ行っていた頃は10年以上のことなのに、昔とお店の雰囲気やメニューはあまり変わっていない気がする。スパイスが効いておいしかった。薬味?トッピング?にサービスで提供されるスモーキーなたくわんや玉ねぎのピクルスもおいしかった。

かぷせる旅籠 赤坂 SPABLIC INN

五反田から赤坂へ行くルートの1つとして、五反田 - 新橋 - 赤坂見附で行ける。乗り換えのアクセスがよかったり、新橋で晩ご飯食べるのもちょうどいい。前から知っていて1度泊まってみたいと考えていた かぷせる旅籠 赤坂 SPABLIC INN に泊まってみた。SPA:BLIC がコーポレートサイトらしい。結論から行って、私の感覚ではすごくよかった。また一泊出張のようなスポットで泊まるときがあれば予約したい。カプセルホテルだから料金は4,471円だった。いまの相場からいうとビジネスホテルでも1万2千円ぐらいするので半額以下と言える。カプセルホテルだから盗難防止を考慮して着替え以外はもっていかなかったが、ちゃんと鍵付きのロッカーもあったのでパソコン程度の荷物なら保管できる。

和風カプセルホテルで施設が新しく、ハイテクであちこちの入館やロッカー、チェックイン/アウトはすべて ic チップで行う。お風呂とサウナはこれといって特徴もなかった気はするが、大きなお風呂に入れるだけで私は満足。コワーキングスペースも併設されていた。休憩プランだと150円/時で使えるらしい。宿泊でももしかしたら使えたのかもしれない。コワーキングスペースが使えるならリモートワークをここでしてもよいのかもしれない。よいところをみつけた。

お盆の最終日

1時に寝て何度か起きて8時半に起きた。数ヶ月に1回ぐらいの頻度でしかないことだけど寝坊した。起きたら8時半であれ?と思った。起きてから家でそのぐらいの時間までだらだらするのはちょくちょくあることだけど、気付かず寝てたのは久しぶりだった。

台風が過ぎた後の焼き鳥屋さん

今朝に寝坊した理由はこれだと思うけれど、昨日の22時から晩ご飯を求めて仲のよい焼き鳥屋さんへ行ってきた。台風で9割以上のお店が閉めている中、唯一と言っていいぐらいの珍しさで開いてた。そのお店 (グループ) のオーナーは雨が降ろうが槍が降ろうが営業日は開けるという方針らしい。マスターも夕方から台風は過ぎて雨も弱まっていたので普通に営業していたらしい。しかし、お客さんは数グループと少なかったと仰っていた。私が22時に行って誰もいなくて24時までいたけれど、誰も来なかった。通常なら22時だと他に2-3グループはいて、その後も最低でも1グループは飲みにやってくるぐらいの人気のある焼き鳥屋さんだ。そもそも駅から人が出てこないし、道にも人が歩いていない。物流も止まっていたのでいくつか仕入れが出来なくて提供できないメニューもあった。

いつもなら2杯飲んで帰るところを、こんな日だから売上に貢献しようと思って3杯飲んで寝坊した気がする。

mongodb 7.0.0 リリース

ちょうど qa テスト前で mongodb のメジャーバージョンがリリースされそうなので毎週のようにチェックしていた。rc10 までいって ga されたみたい。

まだ docker hub には正式なリリースバージョンのコンテナイメージは公開されていない。しかし、rc10 が ga になったはずなのでひとまずはそれを使って開発環境とテスト環境を 7.0.0 に移行した。うちの用途だと ttl インデックスを作り直す以外には移行作業は必要なかった。自動テストはそのまま成功したし、テスト環境のデータもそのまま移行してパッとみた感じでは正常に動いている。来週から qa テストも始まるのでぎりぎり間に合ったというところ。MongoDB Software Lifecycle Schedules によると、だいたい mongodb は3年サポートされる。メジャーバージョンが年に1回リリースされているようにみえるので、いまメジャーバージョンを上げておくと1年余裕をもって運用できる。

テックブログの執筆開始

お昼からテックブログの執筆に着手した。あまり大きな意味はないのだけど、お手伝い先のテックブログの記事を早く3つ書きたかった。別に三部作というわけでもない。けれど、テックブログ書いてますよと他者へ伝えるときに最低3つぐらい記事を書いていないと、全然書いてないやんと私なら思ってしまう。3つぐらいあれば、この人はこういう技術に関心があるんだ、こんな業務をやっているんだ、内容もしっかり書けているねとか、そういう判断を下すことができる最低限のコンテンツ量と言えるのではないだろうか。私にとってはそれが3つの記事と言える。ちょっと前に公開した podcast でテックブログの記事を読んでくださいと話したのでリスナーが聞く前に増やしておきたい。ちょうどプロダクトのプレスリリースも出たのでその宣伝も兼ねられるし、勉強会のネタにもなるし、私の義務感を軽減してストレス解消にもなるし、ここは踏ん張って今日・明日で下書きを書き終えたい。

週明けから疲労困憊

4時に寝て7時に起きた。遅くまでコードを書いていたわけではないけど、眠れなかったのとお腹空いて夜にもぐもぐ夜食を食べていたせいかもしれない。たいてい月曜日は元気いっぱいなのに今日はバテバテだった。

wifi 復旧

金曜日からコワーキングスペースの wifi が不通 になっていた。午前中に業者がフロアの機器室の扉 (施錠されている) を開けて作業していた。週末に復旧できなかったのはシンプルに業者との保守契約に休日対応オプションが入っていなかったのかもしれない。運悪く連休に発生したために約3日間停止していた wifi が11時過ぎにようやく復旧した。フロアにまったく人影がなくて、みんなお盆休みなのかもしれない。

エージェントアプリケーション開発

昨日の続き 。朝からマージリクエストを作ってメンバーにレビューしてもらう。1000行程度の diff になったのでレビューするのも大変。基本的なロジックは問題なかったけれど、メンバーがしっかりレビューしてくれたおかげで細かいところをみていくと、いくつか修正点があった。感謝。レビューを終えて、マージして、テスト環境にデプロイして、一通り動いていることは確認した。ここからは運用レベルの検証に入っていく。週末も昨日もあまり寝てないのもあって、台風がきているし、今日はここで休むことにした。疲れたー。

メモリリークに遭遇

23時に寝て何度か起きて5時に起きてからだらだらネットしながら記事を読んだりしていて7時に起き上がった。

agent アプリケーションのメモリリーク調査

qa テストの一環として先月からテスト環境で毎分 agent アプリケーションにリクエストを投げる長時間稼働テストを実行している。なんとなく気になるところがあったからやったわけではあるけれど、長時間稼働テストによってメモリリークを検出できてしまった。自分を過信せずちゃんと検証しないといけないなと思えた。top コマンドの実メモリー (RES) を1ヶ月前と比較して増えているからメモリリークだと気付いたところ。これからメモリプロファイリングをしながら原因を追求していく。私が書いた (レビューした) go のコードでメモリリークはないだろうと高をくくっていただけにちょっとショックではあった。

go は標準ライブラリに pprof というプロファイラがあるので簡単にデバッグできる。プロファイラで昨日から調査していたところ、go-zeromq/zmq4 の処理でメモリリークしていることはわかった。それがライブラリの使い方が誤っているのか、潜在的な不具合なのかはまだこれから調査するところ。

ライブラリ側の問題を調査するので厄介ではあるけど、私が書いた (レビューした) go のコードでメモリリークしているわけじゃないことがわかって少しほっとした。

go の generics 勉強会

先日準備した資料 を使って勉強会を開催した。

この勉強会はある意味、うちのチームのメンバーが理解しておくべき内容なので go のプログラミングをやっていないメンバーが聞いてもあまり関心をもてない内容となっている。そういうお断りもした上で最悪2-3人ぐらいの参加者になるかと思ったもののプログラミングに関心がある人たちは参加してくれて5-6人ぐらいの規模にはなった。一方で内容も難しいし、私の説明がどれだけわかりやすかったか、私自身にはわからないのでなんとも言えない。質問も一切なかったので喋りきって疲れたという疲労感と、伝わったのか伝わらなかったのか分からない消化不良感と、金曜日だから今日はもういいや感でどっと疲れたというのが率直な感想になる。

とはいえ、私もずっと generics の仕様をちゃんと追いかけたいと思いながら先送りしていたものではあるので私の中では自分が go の generics の理解度をあげて実際の開発の中で使い分けるだけの判断基準をもてたことが収穫だったと言える。

開発の隙間の終わり

1時に寝て何度か起きて7時に起きた。23時に帰ってきて一昨日にお土産にもらったロールケーキだけ食べてしまった。あかんねんけど、おいしかった。

ドッグフードテストと運用談義

リリースしたばかりのプロダクトを社内に導入するべくインフラ作業をしている。社内の管理者が運用を考慮していくつか質問がくる中で、開発側としても運用の考慮の足りないところがあったりして、実運用における不測の自体に対する運用を想定しておく必要がある。こういうやり取り自体が、開発者だけでは得られない知見なので貴重と言える。追加の検証をして、場合によってはなんらかの機能を作ったりする可能性もある。

ドッグフードテストは本当によく出来た仕組みだと思っていて、仮になにか大きな障害が発生してもそれはお客さんのところで発生する前に自社でみつけられればよかったと考えられる。もちろん障害がなければそれはそれで構わない。障害が発生してもしなくてもどちらも開発にとって大きな資産となる。いわゆる win-win のような関係と言える。開発視点から言えばドッグフードテストを行うと決めた時点でうちらはすでに勝っていると言えよう。

プロダクト説明会

毎週やっているチーム勉強会の時間を使って社内向けにプロダクトの説明会を行った。リリースを終えて、その後のドキュメント作りやパッケージングの最適化なども行えた。インフラは十分に機能しているし、ドキュメントも一通り揃っていて、機能はまだまだ足りないけれど、プロダクトとしての体裁はうまくまとまっていると自画自賛している。リソースをかけた分だけスケールするといった開発体制に変化しつつある。おそらく私がマネージャーとして必要なのもあと3-6ヶ月といったところではないか?重要なことは 開発方法論/開発ガイド に書いてあるし、課題管理 + イテレーション開発は特別なことをしなくてもうまくいくことも立証された。メンバーが私と同じように振る舞えば誰でもマネジメントはできるはずである。

来週からは次開発のマイルストーンに入っていく。メンバーが成長して私のマネジメント工数が減るようになってくれば、私も開発に入って下支えすればいいと考えている。まずは3ヶ月でどのぐらいの追加の機能開発が出来ていくのかを見定めたい。

開発合宿の日程確定

そろそろ宿を予約しないといけない。冬の開発合宿 の予定を2024年3月1-3日に決めた。現時点で参加者は4名確定していて、前向きに検討してくれている人が3名いる。昨年が4名だったので倍増して今年は8名程で行ければいいなと希望をもっている。不特定多数に声をかけられるほどキャパシティはないけど、もう3人ぐらい声をかけてもよさそう。

リリース前テストを完了

0時に寝て6時に起きた。昨日は晩ご飯の買いものに行こうと早めに帰ろうとしたら雨降りでそのまま帰って家でだらだらしてた。

リリース前テスト

来週の火曜日がリリース日になる。4月から3週間ほどかけて行ってきたテストケースを完了した。致命的な不具合もなく、テストの過程でみつかった不具合も修正済みで予定していたテストが完了となった。ここ2週間ほど、テストして issue が登録されると、私が細心の注意を払って内容を精査して、即日で fix して検証したりしていた。それもあってテストでみつけた不具合はほとんど fix した。あとはリリースのためのパッケージングやドキュメント作成、インフラ作業などへ移っていく。アプリケーションの振る舞いに影響を与えるものではないので私の中では肩の荷がおりてプレッシャーも軽減されて少し安心できた。よかった。よかった。

docker hub のプライベートリポジトリ

先日 docker hub の rate limit に引っかかったこともあり、docker hub の有償アカウントを使うことになった。team プランは5人以上必要らしいので pro アカウントで契約してもらった。有償アカウントなら無制限のプライベートリポジトリを提供できる。docker hub でリポジトリを作成していて、いまさらながらにリポジトリ名にスラッシュを含められないことに気付いた。基本的にはハイフン区切りでスラッシュの代替する名前になっていた。これまで自分で docker image を扱ってこなかったので今更ながらに気付いた。

社内のコンテナレジストリから docker hub のプライベートリポジトリへの promotion のスクリプトを書いていた。bash の連想配列を使ってコンテナレジストリのマッピングを定義してあとは pull/push するコードを書くだけ。

declare -A repos
repos["internal-my-repo1"]="external/my-repo1"
repos["internal-my-repo2"]="external/my-repo2"
for internal in "${!repos[@]}"; do
  external="${repos[$key]}"
  echo "pull from: $internal"
  echo "push to  : $external"
done

コワーキングのオンラインイベント

月例のカフーツさんのオンラインイベントに参加した。先月の所感はここ 。promotion のスクリプトを書いていたら20分ほど遅れてから参加。今日の話題は chatgpt だった。少し前に 雑談会 したので歴史や原理的な仕組みなど、調べたことを参加者と共有しながら今後の社会の変化などを議論していた。私も関心のある内容なのでおもしろかった。いまや私は日々の開発業務にも chatgpt を使って調べものをしたりサンプルコードを書いてもらうのが普通になりつつある。そのうち ide と連携してテストコードの叩き台なども書かせるようにしてみたい。

いとうさんは chatgpt をみて、人間は働く意欲がなくなるのではないかといった懸念を表明されていた。いまのところ、ドメイン知識をもっている人がより効率よく働けるようになるツールでしかないという私の認識だが、あと3年ぐらいしたら人間を遥かに超えていって、chatgpt の出力をそのまま業務に応用する日も来るかもしれない。llm というのは次にくるもっともらしい単語を膨大な学習データから統計的に選択しているだけで、実際には内容を理解していないし、人間のように創造的な行為もできない。大雑把に言えば、インターネットの空気を読んで発言すれば人間っぽいというのはすごいことだし、便利で役に立つし、働き方も変わっていくだろうけれど、その延長上で変わる世の中が、私の人生における行動に影響を与えるほどではないと考えている。そういった話をする過程であんちぽさんの言う「価値観を育てる」という文脈が頭の中に残っていて、llm ぐらいでは揺らぎそうにはない気がしている。

ただ it 業界以外にもこんなに話題が拡散しているプロダクトはそうそうないので世の中をどんどん変革していくのだろうというのは、異業種の人たちと話していても実感できた。

結合テストのリファクタリング

0時に寝て7時に起きた。前日は久しぶりに飲んでいい気分で寝てた。朝コンビニ寄ったらいつもほぼ満席のイートインが閑散としているなと思いつつ、オフィスへ行って始業報告して、今日祝日だよとツッコミもらった。全然気付いていなかった。まだ新しい天皇誕生日に慣れてない。

go のテストにおける setup/teardown 関数の実装

昨日から結合テストのリファクタリングをしていてせっかくオフィスに行ったので続きをする。結合テストだとデータを作ったり削除したりをテスト単位にやりたい。例えば、ユーザーを作成してテスト実行し、終わったら作成したユーザーを削除したい。次のように setup 関数を書き、返り値として teardown の関数を返す。このときに t.Helper() を呼び出しておくと、エラーがあったときにどの呼び出し元のテストでエラーが発生したかがわかる。

func setupUsers(t *testing.T, users []mongodb.User) func() {
	t.Helper()
	user := mongodb.NewUserCollection(url, username, password)
	for _, u := range users {
		if err := user.Save(u.ID, u.Attributes); err != nil {
			t.Fatalf("failed to create a user: %s", err)
		}
	}
	return func() {
		t.Helper()
		if err := user.Truncate(); err != nil {
			t.Fatalf("failed to truncate the user collection: %s", err)
		}
	}
}

使い方は簡単で setup 関数を呼び出すと teardown 関数が返ってくるのでそれを defer で呼び出すとよい。

teardown := setupUsers(t, usersTestData)
defer teardown()

しかし、この setup 関数をサブテストと一緒に並行実行すると意図したように動かない。どうやらサブテストを並行実行すると親テストが呼ばれた後に呼び出されるという仕組みになっていて、サブテストを実行する前に teardown が呼ばれてしまうので意図した制御にならない。How to handle parent test teardown with parallel subtests in golang の回答 によると、サブテストからさらにサブテストを実行するとよいとある。この場合、親テストとサブテストは同期的に実行され、サブテストの中でさらにサブテストを並行実行するという考え方で意図した振る舞いになる。並行実行するときは次のようなコードになる。

func TestMy(t *testing.T) {
    tests := []struct{
        // test cases
    }

	teardown := setupUsers(t, usersTestData)
	defer teardown()

	t.Run("wrap for setup process", func(t *testing.T) {
		for _, tt := range tests {
			tt := tt
			t.Run(tt.name, func(t *testing.T) {
				t.Parallel()
                // do test
            })
        }
    })
}

お仕事戻し

お仕事戻し

0時に寝て5時に起きた。昨日も疲れていたのか、不思議とよく眠れた。

年末のお仕事戻し

朝から近所のマクドナルドへ。今週は月・火とお休みしたため、いつも火曜日に書いている週報を書いていなかった。言うても3日分の作業なのでちゃっちゃと書いて送付した。私が休んだ日の定例会議はスキップされたようでその確認はなし。その後、issue のコメントをみたり、マージリクエストのコードレビューをしたりした。メンバーが課題管理システムを使うようになっているので、私が休んでいても後で見返してコメントを返せる。非同期/テキストコミュニケーションは働く時間帯があわないときに役に立つ。そういう雰囲気を学ぶ機会になればいいかもしれない。ある文字列の変換関数に go 1.18 で追加された fuzzing テストを実装してみようというリファクタリングの issue を追加していた。

私自身、まだ自分で実装したことはなかった。fuzzing テストを実装したマージリクエストがあったのでコードレビューした。実際に実行して動いているようにはみえるが、デバッグログを出力できなくてどういった振る舞いをしているのかを確認できなかった。簡単にできるんやと思っていたら意外と難しかった。また後で自分でも実装してデバッグしてみて振る舞いを再確認する。

小さい椅子

葬儀で斎場に2泊3日過ごしたときに畳の控え室に小さい椅子が4つほど置いてあった。正座が難しいお年寄り向けだと推測する。あの控え室でその小さい椅子を最も活用していたのは私だった。地べたに座るのと小さな椅子に腰掛けるので腰の負担がこんなに違うとは思わなかった。おそらく太ったことも影響している。ラップトップでキー入力するときに正座にしろ、あぐらにしろ、どちらも長時間続けることはできなかった。この小さい椅子なら2-3時間ぐらいは平気で作業できる。気持ち程度の高さでも十分に椅子の役割を果たせるところに感心した。家用に購入して、いま小さい椅子でこの日記を書いている。

dind をやってみた

3時に寝て7時半に起きた。最後なのでワールドカップの決勝戦をみてた。接戦で試合もおもしろかったしよかったと思う。

gitlab ci/cd で docker in docker

ミドルウェアを伴う結合テストは dockertest というツールを使って docker でミドルウェアを起動して実行している。デフォルトで作成した gitlab runner で docker を使おうとすると失敗する。これは gitlab runner が ci/cd ジョブを docker で動かすため docker in docker (これを dind と呼ぶらしい) のための設定が必要になる。大雑把に言えば gitlab runner にそのための権限を設定する必要がある。gitlab の次のドキュメントに詳細が書いてある。

gitlab runner に権限を設定したら次のような job が動けば docker in docker は成功と言える。

hello-dind:
  stage: test
  image: docker:20.10.21
  variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""
  services:
    - docker:20.10.21-dind
  allow_failure: true
  before_script:
    - docker info
  script:
    - docker run hello-world

あとになって気付いたことだけど、dockertest の README にも Running dockertest in Gitlab CI としていくつか tips が紹介されている。dockertest で作成したリソースからホスト名とポート番号を取得するには次のようなユーティリティを使う必要がある。

func getHostPort(resource *dockertest.Resource, id string) string {
	dockerURL := os.Getenv("DOCKER_HOST")
	if dockerURL == "" {
		return resource.GetHostPort(id)
	}
	u, err := url.Parse(dockerURL)
	if err != nil {
		panic(err)
	}
	return u.Hostname() + ":" + resource.GetPort(id)
}

go の学び直し テスト編

23時に寝て2時に起きて気分悪くて寝付けずにだらだらしながら気付いたら5時になっていた。その後いつの間にか寝て8時に起きた。

go の学び直し

Gopher塾 #1 - Testing - DAY 3 に参加した。

マネージャーとして go 開発のマネジメントをしているため、メンバーの開発者よりは知識やスキルが高くないとコードレビューや適切な指示ができない。2018年ぐらいまで go 開発をしていたが、その後はずっと java 開発をしていたため、最近の go 開発の話題はあまり把握していない。毎週チーム勉強会 (いまのところ、go 開発の話題) をやっていると、チーム外からも開発者が参加してくれるようになった。チーム外からの開発者が go 開発するときの参考にもなるよう、マネージャーのお仕事の付加価値として、組織全体へ go 開発の知識やスキルを提供できればと考えながら働いている。

今回はテストについて話題で7割ぐらいは知っている知識ではあったが、3割ぐらいは最近の話題や静的解析の知見からの深い洞察を話されていてとても参考になった。知っている知識でも幅広いテストの話題の中で厳選されたコンテンツになるのだろうから本質的に大事なことや最初に学ぶべき優先事項を知ることもできた。私がメンバーに教えるときのコンテンツの参考として役に立つ。まったく知らなかった話題としては、txtar というテキストをアーカイブしたフォーマットをファイルシステムとして扱えるようにした txtarfs や、1.18 から追加された fuzzing というテストの入力値を自動生成する機能が追加されたこと。あと groovy でいうところの power assert に近い機能を提供するライブラリとして google/go-cmp をいまはテストに使うらしい。たまたま Go Test Comments を読んでいたら go-cmp は go の開発チームが保守していて go のバージョンに依らずほとんどの比較の要件にあうツールのように説明されていて利用を推奨している。

久しぶりに go のテストコードを書いた

0時に寝て3時と5時に起きて7時に起きた。まぁまぁ眠れたと思う。

go のテストコードのサンプル

先日 Logger のコード を書いて、テストコードのサンプルも書いてみた。いま微妙に TableDrivenTests が書けてないので参照実装として Logger のデータ駆動テストを書いてチームに共有した。私も future さんのテストのチュートリアル記事を読みながら復習してた。

昔、私が go 開発していた頃にはなかった新機能としてサブテストを並列に実行できる。

uuid ライブラリの歴史的経緯

たまたま Version 1 UUID を返す NewUUID のコードをみていて、err を返しているけど、現時点の実装では err が返ることはなく、これは歴史的経緯でシグネチャを変える方が影響が大きいだろうという意図でそうなっているらしい。

ここでは New を使えとも書いてあるけれど、これはエラーが発生したときに panic が発生するのでこれはこれでいいんやろか?という疑問も出てくる。