Posts for: #Testing

練習場所のビル探し

今日のバドミントン練習はリフティングを昼夜あわせて85分 (メイビスで75分、エアで10分) した。フォア持ちとバック持ちを交互に切り替えリフティングで398回続けられた。目標の200回を越せるようになった。

バドミントンの練習場所探し

お昼休みに公園へ行って20分ほど軽く練習した。そのときに連続回数が198回だった。あと2回足りなかったのが悔しかったのと、夜にがんばったらできそうかなという見通しをもっていた。

夜は近所で練習場所によさそうなビルを探してまわってみた。まずは少しおしゃれな区役所のビルの軒下へ行ってみた。

たまたま時間帯が悪かったのか、この場所が風の通り道になっているのか、練習を始めて5分ほどやって風の影響が強くて難しそうだったのですぐに撤収した。人通りが少なく照明もよい感じなのだけど、バドミントンの練習は風が強いとどうにもできない。

付近を散策しながら旧居留地にある別のビルへ。従業員の通用口がやや近いところが懸念。従業員が出てきたときにこいつ何しているの?と思うかもしれない。私の視点からもややパーソナルスペース/練習スペースを狭く感じるところはある。風の影響は受けにくい構造にはなっている。ここで15分ほど練習して267回継続できた。初めて200回を超えた。その後、あまり回数が続かなくなったのでまた散策して別のビルへ。

ここも広くて明るくて夜は施錠しているようにみえる。ここは従業員と会うこともない。よい場所なんだけど、照明が明る過ぎて見上げたときにシャトルと照明が重なってしまうと眩しい。照明が明る過ぎても練習しにくいことに気付いた。ここでも20分ほど練習したのに200回を超えなくて次へ移動する。照明が目に入るせいかもしれない。

最後はホームのビルへ。他のビルで練習してみてホームのビルのよさを実感した。もっとも練習スペースが広い。そして照明を背中側にして練習するスペースも十分にある。そうすると、見上げても照明とシャトルが重なることはないので眩しくて失敗してしまう状況を避けられる。構造的に風の影響も受けにくい。ここで20分ほど練習していたら398回、266回、349回と200回超えを3回できた。

フォア持ちとバック持ちのリフティングをしていて安定的するようになってきた。うまくラケットのスィートスポットで打てば真上にシャトルが上がる。50回ぐらいならほとんど動くこともなく上げられる。だいたい100回に1-2回ぐらい、失敗してシャトルをラケットのフレームに当てたりしてシャトル操作が乱れる。ドタバタしてリカバリする。これまではそのときに焦ってしまってシャトルを落とすことが多かった。なぜ200回以上続くかというと、その稀に失敗したときのシャトル操作をリカバリできるようになってきたから。つまり5回ぐらいミスしたときにリカバリできれば200回は続くということになる。これはメイビスフィールドのシャトルを使ったときの話し。

次にエアシャトルを使って同様にリフティングをしてみると最高で50数回ぐらいしか続かない。これはラケットのフレームまたはフレーム近くのガットで弾いてしまうと、コルク部分がプラスチックなために反発せずに落としてしまったり、あらぬ方向へ飛んでいったりしてリカバリがとても難しい。つまり、ラケットコントロールをうまくやらないとエアシャトルでリフティングを継続するのはメイビスフィールドよりもずっと難しい。次の目標としてはエアシャトルで200回を越せるようにラケットコントロールの練習をするのがよいように思える。

テストとビルドタグ

go ではテスト用途のパッケージを httptestiotest といった、通常アプリケーションとしてパッケージを提供しているものもある。しかし、通常のパッケージにしてしまうと、アプリケーションをビルドしたときにテストコードもバイナリにも含まれてしまう。依存パッケージの管理やバイナリサイズを減らす上で不要なコードはビルド対象外になる方が望ましい。自分たちが書いたソースコードがアプリケーションに含まれることはサイズの視点では問題ないが、テスト向けの依存パッケージもアプリケーションに含まれると意図せずバイナリサイズが大きくなってしまったり、パッケージの依存解決に時間がかかったりしてしまう懸念がある。そのため、ビルドタグを用いてテスト用途のパッケージはテストのときしかビルドしないように制御する。

例えば integration というビルドタグを設ける。テスト用途の util パッケージを定義するときは次のようにソースコードを記述する。

//go:build integration

package util

ビルドタグを指定せずに結合テストを実行しようとすると次のようなエラーが発生する。

$ go test ./tests/...
# example.com/tsets/mypackage
package example.com/tsets/mypackage_test
	imports example.com/tests/util: build constraints exclude all Go files in path/to/tests/util
FAIL	example.com/tests/mypackage [setup failed]

結合テストを実行するには次のように明示的にビルドタグを指定して、テスト用途のパッケージをビルドしてテストが実行されるようにしないといけない。

$ go test -tags=integration ./tests/mypackage/...

openldap スキーマの validator と go のマルチエラー制御

今日もメンバーのコードレビューに半日以上の時間を割いたので自分の時間をあまり取れなくて開発が進捗しなかった。

隙間時間で openldap スキーマの情報 を使って validator を実装していた。バリデーションのようなものはまとめてエラーを返せるのが望ましい。go でマルチエラーを制御する仕組みが少し前に追加されていたことを思い出した。Go 1.20 Wrapping multiple errors のチュートリアル記事を読みながら openldap スキーマの validator を実装して複数のエラーを返すようにした。まだ抜け・漏れはあるかもしれないけど objectClass の validator は次のようになる。

type ObjectClassValidator struct {
	objectClassMap map[string]ObjectClassDescription
}

func (v *ObjectClassValidator) Validate(attr map[string][]string) error {
	var errs []error
	var objClassDescs []ObjectClassDescription
	hasStructuralKind := false
	allAttrMap := map[string]struct{}{}
	lowerAttrNameMap := make(map[string]struct{}, len(attr))
	for k, values := range attr {
		lowerName := strings.ToLower(ParseAttribute(k))
		lowerAttrNameMap[lowerName] = struct{}{}
		if lowerName == "objectclass" {
			objClassDescs = make([]ObjectClassDescription, 0, len(values))
			for _, objcName := range values {
				lowerObjcName := strings.ToLower(objcName)
				ocd, ok := v.objectClassMap[lowerObjcName]
				if !ok {
					msg := fmt.Sprintf("'%s' objectClass is not defined", objcName)
					errs = append(errs, NewErrorValidation(msg))
					continue
				}
				if ocd.Kind != nil && *ocd.Kind == Structural {
					hasStructuralKind = true
				}
				objClassDescs = append(objClassDescs, ocd)
				for mustAttr := range ocd.GetMust() {
					allAttrMap[strings.ToLower(mustAttr)] = struct{}{}
				}
				for mayAttr := range ocd.GetMay() {
					allAttrMap[strings.ToLower(mayAttr)] = struct{}{}
				}
			}
		}
	}

	// require at least 1 structural objectClass
	if !hasStructuralKind {
		errs = append(errs, NewErrorValidation("no structural objectClass"))
	}

	// must in objectClass requires must attributes
	for _, ocd := range objClassDescs {
		for mustAttr := range ocd.GetMust() {
			if _, ok := lowerAttrNameMap[strings.ToLower(mustAttr)]; !ok {
				msg := fmt.Sprintf("'%s' objectClass requires '%s'", ocd.GetName(), mustAttr)
				errs = append(errs, NewErrorValidation(msg))
				continue
			}
		}
	}

	// all attribute keys are allowed may/must in objectClass
	for attrName := range lowerAttrNameMap {
		if _, ok := allAttrMap[attrName]; !ok {
			msg := fmt.Sprintf("'%s' is not allowed by objectClass", attrName)
			errs = append(errs, NewErrorValidation(msg))
			continue
		}
	}
	return errors.Join(errs...)
}

func NewObjectClassValidator(
	objectClasses []ObjectClassDescription,
) *ObjectClassValidator {
	ocm := make(map[string]ObjectClassDescription, len(objectClasses))
	for _, v := range objectClasses {
		for _, n := range v.Name {
			ocm[strings.ToLower(n)] = v
		}
	}
	return &ObjectClassValidator{
		objectClassMap: ocm,
	}
}

次のように複数のエラーを返すテストケースを定義する。

{
	name:       "multiple errors",
	objClasses: objectClasses1,
	attr: map[string][]string{
		"objectClass":           []string{"top", "posixAccount", "myObjeClass"},
		"uid":                   nil,
		"mail":                  nil,
		"mail;lang-ja;phonetic": nil,
		"employeeType;lang-ja":  nil,
		"homeDirectory":         nil,
		"GIDNumber":             nil,
		"street":                nil,
	},
	expected: []error{
		openldap.NewErrorValidation("'employeetype' is not allowed by objectClass"),
		openldap.NewErrorValidation("'mail' is not allowed by objectClass"),
		openldap.NewErrorValidation("'myObjeClass' objectClass is not defined"),
		openldap.NewErrorValidation("'posixAccount' objectClass requires 'cn'"),
		openldap.NewErrorValidation("'posixAccount' objectClass requires 'uidNumber'"),
		openldap.NewErrorValidation("'street' is not allowed by objectClass"),
		openldap.NewErrorValidation("no structural objectClass"),
	},
},

テストコードで次のように返ってくる error を unwrap することで検証できる。

for _, tt := range tests {
	t.Run(tt.name, func(t *testing.T) {
		t.Parallel()
		validator := openldap.NewObjectClassValidator(tt.objClasses)
		err := validator.Validate(tt.attr)
		if actual, ok := err.(interface{ Unwrap() []error }); ok {
			t.Log("\n" + err.Error())
			if diff := cmp.Diff(tt.expected, actual.Unwrap(), opts...); diff != "" {
				t.Error(diff)
				return
			}
		}
	})
}

集中開発の1ヶ月間

プロジェクトの進捗報告

出張したときの月例報告の19回目。前回の進捗報告はこちら 。この開発フェーズは私が経営陣へ進捗報告するものの、引き継いだマネージャーにも同席してもらって、こんな打ち合わせをしているというのを知ってもらう機会にしている。この1ヶ月間の進捗やこの開発フェーズでやろうとしていることを一通り説明して、あとはざっくばらんに経営陣と雑談するといった機会にもなった。最低限、開発のボトルネックになりそうなところは私が集中開発して解消したので見た目上はよいペースで進捗している。

進捗報告して雑談しているうちに、もうこれ以上は私がお手伝い先へ提供できる新たな価値はなさそうに思えてきた。ここからは課題管理できている issue を優先度順にひたすら fix していく、よくないところはリファクタリングする、開発の負債やボトルネックを解消していくといった、より実践的な実務が求められる。課題管理を含むプロジェクトマネジメントやチームの情報共有を改善することで開発をうまくまわしていくフェーズは十分にメンバーが実践できるようになったと思える。自身の引き出しの中身を払い出してしまって、なにも残っていないような寂しさを感じるようになった。

いまマルチブラウザ/デバイスのテストの自動化のために BrowserStack というプラットフォームを評価している。まだ評価中なので採用の可否はこれから判断するところだが、採用したらコストがかかるのでその話題も経営陣に伝えてその場で議論したりしていた。おそらくこのサービスは Selenium Grid を使っているのではないか?と推測される。うちのプロジェクトだけでなく、社内インフラとして全社共通のテスト基盤を作るという施策もあるかもしれないと話しが発散したりもした。開発においてプラットフォーム的な投資も大事だと考えられている。うちのプロダクトで作る課題管理のメトリクスに、プラットフォーム投資のための見える化ができる機能もあるとよいのかもしれないと思ったりしていた。

multipart/form-data リクエストの扱い

9時に起きて2度寝して10時頃に起きたものの、お昼までだらだらしていた。それからオフィスへ行って溜まっていた日記をまとめて書いて、逃げ上手の若君 をみながら作業をしていた。来週は出張の週だから事前にやっておくことがいくつかある。

ストレッチ

先週は実家へ帰っていた ために2週間ぶりのストレッチになる。とはいっても、いまは運動をしているので筋肉痛もない。しかし、机に向かってデスクワークする時間が増えている分の負荷がかかっている。トレーナーさんからも腰から背中にかけて硬いと指摘された。今日は硬くなっているカラダ全体をほぐしてもらった感じだった。おかげで今後も体調よく机に向かえる。今日の開脚幅は開始前149cmで、ストレッチ後155cmと普段通りの数値だった。

multipart/form-data リクエストを扱う結合テスト

昨日の夜に汎用のファイル操作の api を実装した。今日はその結合テストを追加してマージリクエストを作成した。multipart/form-data のリクエストを作るのはちょっと面倒くさい。go のライブラリのテストコードや stackoverflow のサンプルコードなどを調べながら自分で実装した。次のような multipart/form-data リクエストを扱う writer や buffer を生成するためのユーティリティを作る。一通りの結合テストを実装するのに3時間ほどかかった。

func createMultiPartFormData(
	fileBody []byte, formField map[string]string,
) (*multipart.Writer, *bytes.Buffer, error) {
	b := new(bytes.Buffer)
	mw := multipart.NewWriter(b)
	for k, v := range formField {
		fw, err := mw.CreateFormField(k)
		if err != nil {
			return nil, b, err
		}
		if _, err := fw.Write([]byte(v)); err != nil {
			return nil, b, err
		}
	}
	fw, err := mw.CreateFormFile("file", "path/to/file")
	if err != nil {
		return nil, b, err
	}
	if _, err := fw.Write(fileBody); err != nil {
		return nil, b, err
	}
	if err := mw.Close(); err != nil {
		return nil, b, err
	}
	return mw, b, nil
}

このユーティリティを使って http リクエストのテストデータを生成するのは次のようなコードになる。

u := &url.URL{
	Scheme: "http",
	Host:   "localhost",
	Path:   path,
}
mw, body, err := createMultiPartFormData(fileBody, formField)
if err != nil {
	return nil, fmt.Errorf("failed to create multipart form data: %s", err)
}
req, err := http.NewRequest(http.MethodPost, u.String(), body)
if err != nil {
	return nil, fmt.Errorf("http create new request error. err: %s", err)
}
req.Header.Set("Content-Type", mw.FormDataContentType())

あと結合テストでファイルをアップロードすると実際にファイルシステム上に保存されてしまうのでそれらを削除するには Cleanup を使うと簡単に後始末できた。

func TestFileUpload(t *testing.T) {
    ...
	t.Cleanup(func() {
		if err := os.RemoveAll(file.FilesDir); err != nil {
			t.Errorf("failed to remove files directory: %s", err)
			return
		}
	})
    ...
}

プロジェクトのボトルネック解消

今日は開発の設計に関する打ち合わせが2つ入っていて、どちらも私はメインではないものの、メンバーが要件ヒアリングしやすいよう、ハドルで話しを聞きながらチャットにコメントしたり質問したりしてサポートしていた。その合間に ldap サーバーのグループメンバー管理のための api を実装していた。いま ldap client はライブラリとして作っている。docker-openldap というコンテナを使って dockertest で単体テストを実装している。openldap サーバーに対する ldap プロトコルの操作を容易にテストできるので開発がやりやすい。新規にグループメンバーを操作するための api をライブラリとしての ldap client に実装し、その後に web api としての機能を提供した。だいたい1日で完了した。この2週間ほど取り組んでいた、開発フェーズにおける私のボトルネックをこれで解消できた。ここからは私がやりたい開発ができるボーナスステージへと移行していく。これで少しストレスやプレッシャーが減っていくはず。

今週はテストに集中

今日の運動は腹筋ローラー,縄跳び(両足跳),散歩,ジョギング,ハンドグリップ,ダンベルをした。統計を 運動の記録 にまとめる。縄跳びの前後に 右股関節の改善体操 をした。

テスト作業は今週いっぱい

来週の月曜日はお休みで火曜日がリリース日なので今週いっぱいが QA テストの最終週になる。いろいろ背景があって進捗はよくなくて、できるところまでやりましょうといった状況になっている。いろいろよくなかったことのふりかえりは後でやるとして、そうは言ってもできることをできる限り、懸念点は潰しておきたい。今週はテストだけに集中して取り組む。

みなとのもりの運動

前回の所感 。引っ越ししたことでオフィスよりも住居から公園への距離の方が近くなった。それで公園で運動するときのアイテムを入れたバッグを、オフィスから住居へ移していた。オフィスを退勤して公園へ向かう途中で住居に立ち寄り、バッグを取って公園へ行く。この寄り道が意外と面倒くさい。2週間ほどやってみて結論として慣れない。なにが面倒なのかな?と考えて思いつくのがエレベーターの乗り降りではないかと思う。エレベーターの乗り降りにかかる待ち時間は合計しても2-3分でしかないはずなのに、待って、上がって、荷物を取って、また待って、降りてくるという待つ手順が多い。この待ち時間が運動しようというテンションに悪い影響を与える。心理的によくない。

出勤するときに運動アイテムのバッグを持ってオフィスに置いておき、オフィスからバッグをもって直接、公園へ行く。運動が終わったらバッグを持って直帰するというサイクルがよいのではないかと考えた。しばらくやってみる。

テストの依存関係をステージで表現する

今日の運動は腹筋ローラー,腕立て,縄跳び(両足跳),散歩,ジョギング,ハンドグリップをした。統計を 運動の記録 にまとめる。

qa テストの設計

システムや機能が複雑になった後の qa テストをどう設計するか。先日 Full Stack Testing を読んで考察 したりしていた。テストでもっとも工数がかかるのはデータや設定も含めてテストできる環境を構築すること。gitlab ci/cd で3つのテスト環境を構築しているものの、それらと qa テストのテストケースとどうやって関連させるか、またはテストの依存関係をどのように表現するかといったことを設計の重要事項として考察していた。

これまで google sheets の1ファイルですべてのテストケースを管理していた。しかし、機能が増え、テストケースが増えていくにあたり、この1ファイルにより管理は破綻しかけていた。id 連携という、複数のシステムまたはモジュールを介してデータをやり取りするというアプリケーションの特性上、テストの依存関係は google sheets の1ファイルでは表現できない。そこで「ステージ」という概念を導入し、google drive のフォルダや階層構造で依存関係を表現することにした。ステージ1のテストが成功しない限り、ステージ2のテストが成功することはない。業務における本質的な難しさである依存関係を人間にとってどう管理していくかが重要になる。急にこれらの qa テストをすべてできるわけではないが、ステージを3つまで定義した。最後の手動探索テストを issue の創発という、課題管理にとって重要な位置づけにおさめたのが個人的にお気に入り。実際に手動探索テストをどのように実施できるか?というのはまだまだこれからの課題ではあるが。

  • ステージ1
    • 2つのシステム間におけるテスト
    • 特定モジュールの振る舞いの検証
    • ui 周りのテスト
  • ステージ2
    • 複数のシステムをまたがるテスト
    • 機能横断的な要求テスト
      • 可用性に関するテスト
      • エラー制御に関するテスト
    • アプリケーションの機能が動作した次にある高度な要件
      • セキュリティテスト
      • パフォーマンステスト
      • アクセシビリティテスト
  • ステージ3
    • 手動探索テスト
      • issue の創発

テスト設計についての考察

飲みにいっていたので今日の運動はお休み。

都営浅草線

宿泊したホテルの近くにある三田駅から五反田まで都営浅草線で乗り換えなしで通勤できることに気付いた。山手線でも行けるが。芝公園は運動にもよいスポットなので五反田の京王プレッソイン以外にスーパーホテルに泊まるプランも織り交ぜてよさそうに思える。

QA テストのテスト設計

次のマイルストーンから QA テストが始まる。その前に今回の開発した成果物を踏まえてテストケースなどを整備し直さないといけない。さらに機能が増えてシステムが複雑化したことでテストのカテゴライズなども見直したいと考えていた。そういった一連のテスト設計を再構築しようと考えている。一般的なやり方としてテストケースをスプレッドシートでまとめる手法がある。それ自体は悪くないし、デフォルトのやり方だとは思うが、もっとよいやり方はないかと模索している。試しにオライリーのサブスクリプションでみつけた Full Stack Testing の、関心のあるところだけ斜め読みした。

これまでは手動テストと自動テストの2つのカテゴリ程度でしか分類されていなかったテストに関するコンテキストを、著者は10個のスキルに分割して体系化し、これらをまとめて full stack testing と呼んでいる。適切な名前をつけられることから著者のテストに関する知識や経験の深さが伺える。

いくつか斜め読みした中で私が最も関心をもったところに手動探索テストの章がある。著者は「手動テスト」と「手動探索テスト」はまったく別の概念であると定義している。前者はあらかじめ決められたテスト仕様にしたがってテストするだけ。後者はアプリケーションの詳細を掘り下げ、現実的なシナリオを考えて、それらをシミュレートするようにテストしていく。

この開発後の探索的テストを実施するために、別個の担当者を配置する必要はないかもしれない。しかし、そのアプローチの方が、アプリケーションに関する知識が蓄積され、鋭い観察力と分析力を持つ人が必要になるため、より良い結果が得られるかもしれない。コストや稼働率の問題でこれができない場合は、既存のチームメンバーが、各イテレーション期間中、総当り方式で探索的テストを実施する責任を負うべきである。実際、探索的テストのスキルを開発することは、すべての役割のパフォーマンスを向上させるのに役立つかもしれない。

探索テストをやるときはその人の経験に応じて感覚的にあちこち触ってテストをしているように思う。次の図は、その分類を明確にすることでチェックポイントやテストのコツやプラクティスの共有をやりやすくなっていくかもしれないと思えた。

雑談会

夜はやぎさんとおがわさんと久しぶりに会って雑談してきた。おがわさんとは1年以上会っていなかったと思う。実家が大阪なので帰ってきたら声をかけてくださいとよく伝えているものの、最近は実家に帰っておられないようだ。うちは最低でも年に1回お正月に帰るのが当たり前の家だったから何年も実家に帰っていないという家族の形態もあるんだなという所感。それぞれの家の文化がある。ホットクックで 麻婆なす を作ろうという話題になって、私も作ったことがないことに気付いた。今度うちでも作ってみようと思う。あと、まったく飲んだことのなかった焼酎で 十割そば焼酎粋蕎 (いっきょう) がおいしかった。近所の酒屋でも売っているか探してみよう。

スマート縄跳びを購入

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 アニメストアならみていなかったかもしれないけど、テレビならストレッチしながらついついみてしまった。そういう視点ではテレビの価値は大きいのかもとも思えた。