テストのためのNotionエンジニアリング ／ テストカバレッジをNotion管理できるようにしました

こちらは [ソフトウェアテスト Advent Calendar 2024](https://qiita.com/advent-calendar/2024/softwaretesting) の10日目の記事です。

# はじめに
西薗（[@yurizono](https://x.com/yurizono)）です。ニューズピックスでQAエンジニアをしています。この前、[Software Design 2024年12月号で記事を書きました](https://x.com/yurizono/status/1858841598135796024)。よし良かったらそちらもご覧ください。

# 概要
私のチームで管理しているテストケース（リグレッションテストとして月一、社外に依頼して実施しているもの）と、それに紐づけられた機能一覧をスプレッドシートからNotionに移行した話をします。

Notionを使った情報管理の一つの例として、またNotion導入を悩んでいる方のヒントになれば幸いです。

# 前提
リグレッションテストのテストケースが私の入社前から存在していたのですが、数が多いのと長年のメンテで見通しが悪くなっており、思ってもない機能が実はテストされていなかった、ということが発生していました。そこで機能一覧という表を作り、それをテストケースと紐づけることでテストカバレッジを計測しました。[テストカバレッジはテストの家計簿だよねって話](https://tech.uzabase.com/entry/2022/12/09/000000)という記事で詳しく説明しています。

この時点では、テストケースと機能一覧はスプレッドシートで管理していました。この二つの紐付けはどうしていたのかというと、機能一覧の方の各行にキー（例えば `一般-記事---R-記事を閲覧する` のようなものです）を振り、それをテストケース表の端っこに記載していました。

ギリギリなんとかメンテはできていましたし、カバレッジもスプシ上で確認できていましたが、例えば「記事を閲覧する」という機能には動画の話も入っているなと気付いたので「記事・動画を閲覧する」に書き換えたりすると、キー名も一緒に変わってしまって壊れる……みたいな事態がまま発生していました。

こいつを何かツールに乗り換えたいなと考えていたところに、全社的にNotionが導入され、ならばNotionにしてしまおうと考えたのが今回の話の始まりです。

# そもそもNotionとは
そりゃドキュメント管理ツールだよ、なんですが、私の理解は少し違います。別の記事でも書いたので、そちらから抜粋。

https://qiita.com/yurizono/items/49d444457c8dfdae0a63

> 私の理解では、Wikiというフロントを持ったデータベースです。複数のテーブルを定義でき、各レコードはwikiページとして編集が可能。また全てのページどころか、ページ内の全ての要素にいたるまでが個別のURLを持ちます。
> 
> 自動化の機能も豊富で、後述するAPIを使う方法を含め、いろんな外部ツールとも連携が可能。いまどきの、多種多様なSaaS製品を使う職場環境とよくマッチしたのでしょう、ここ数年で一気に利用が広がったようです。
> 
> 私も、大抵の用事はNotionで出来ちゃう、と思い始めました。これは令和のエクセルですよ。私が勝手にそう呼んでるだけですが。

# 作ったものを紹介
NotionDBを2つ作りました（実際は3つあるんですが、説明用に単純化しました）。テストケースと機能一覧で、この2つのDB間にRelationが張られています。

テストケースがNotionに入りましたが、これを使う（実行する）ときはスプレッドシートにエクスポートしています。マスター管理だけがNotionになったわけですね。なんだかんだ、テスト実行のときはスプレッドシートが便利です。

![Screenshot 2024-12-09 at 13.24.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2963124/0d3752a7-b516-6707-ea41-77e114c1674d.png)

機能一覧の方はsub-itemsという機能を使っていて、レコード間に親子関係を持たせた上で、いろんな単位でカバレッジを確認できるようにしています。

![Screenshot 2024-12-09 at 13.24.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2963124/3ab5d0f4-bf23-6d6e-50aa-40cee706d50b.png)

## 機能一覧DBについて少し詳しく説明
> レコード間に親子関係を持たせた上で、いろんな単位でカバレッジを確認できるようにしています。

この階層を実現するためには、RollupやFormulaというプロパティタイプを使う必要があります。

- **Rollupプロパティ** ： 指定のRelationを辿って、紐づけられたレコードの指定のプロパティを見て合計や平均値を計算することができる。 → [Using relation & rollup properties](https://www.notion.com/help/guides/using-relation-and-rollup-properties)
- **Formulaプロパティ** ： いわゆる数式、色々できます。 → [Intro to fomulas](https://www.notion.com/help/formulas)

具体的には、機能一覧DB全体を単一の根を持つ木構造と捉え、各ノードで Descendant subtrees（自分を含まない、子ノードを根とする全ての部分木）の`sc`（シナリオ数、ノード数）および`cv`（テストでカバーされたシナリオ数、isCovered==trueであるノードの数）をRollupで求めたあと、subtree（自分を含む部分木）の`sc`および`cv`をFormulaで算出します。Descendant subtreesを計算するために、子ノードのsubtreeを使いますから、以下のような関係です。

![Screenshot 2024-12-09 at 17.28.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2963124/53e5fb7f-a952-49a1-b56f-859727838044.png)

なぜ二種類のプロパティタイプを使ったのか？というと、こういう事情があります。

- RollupプロパティからRollupプロパティを参照することはできない。ただし、Formulaプロパティを参照するのは構わない。
- RollupおよびFormulaプロパティは、それが別レコードであったとしても自己参照はできない。

したがって、再帰的にカバレッジを計算するためには Rollup → Formula → Rollup という形で、間にFormulaを挟んでやる必要がありました（厳密に言えばFormulaプロパティ2つでも出来ると思います）。

# 運用

こうして作成したテストケースと機能一覧を弊チームで運用しています。

ケース修正や機能一覧への項目追加などは開発チームにもお願いしていて、修正されるとNotionのAutomationが動いてSlackに修正内容を投稿してくれたりします。それをQAが見て事後的にレビューをしています。

またカバレッジの数字は毎日変動しますが、その値は毎日深夜にZapierでスプレッドシートに連携し、グラフ化した上でダッシュボードに表示しています（Notion Chartに移行できるかも？）。テストケースの修正を頑張った翌日なんかはカバレッジが大きく上がり下がりします。最新の数字だけではなく数字の上がり下がりが見えるようにしておくことで、チームのモチベーション向上にも貢献してくれています。

# Notionに移行したメリット
まず何より、Relationの管理が段違いに楽になりました。
- RelationプロパティをDBに追加するだけで紐付けが可能
- 名前など、他のプロパティを書き換えても紐付けが切れない
- 紐付け先が消えると勝手に紐付け自体も削除されるので、ゴミが残らない
- 紐付けを予めつけた状態で機能やテストケースを作成できる（ビューの使用）

また運用のところで書いたように、外部ツールとの連携の自由度が上がりました。

# Notionに移行して困ったこと
表形式でデータを見られる、しかも相当大量のデータがあっても重くならずサクサクと見られるというのはスプレッドシート（Google Spreadsheetを使っていました）の大きなメリットでした。Notionはそこまでのサクサク感はありません。

また、スプレッドシートの方が検索や置換といった作業は段違いに楽です。テストケースもNotion上で追加や修正をしているわけですが、まず検索・置換ができないのでちょっと文言を書き換えたい、といったときに困ります（「ニュースタブ」を「ホームタブ」にすべて書き換えたい、など）。

## プロパティの参照制約について

また、複数のレコードを参照してのデータ集計などが比較的苦手で、正しい数字を出してくれないことがあります（[参考](https://thomasjfrank.com/formulas/property-reference-limits/)）。

具体的には、プロパティ間の参照は15段までしか処理してくれません。16段に達すると結果がエラーになります。なお、2024年7月までは7段までだったので、幾分マシになりました。

![Screenshot 2024-12-09 at 13.45.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2963124/1b851e51-6933-c429-0405-65c096d1560c.png)
（[Reference Chain Limits](https://www.notion.so/Reference-Chain-Limits-5fba0f9a3223417ba134699fe1084e69?pvs=21) を参考にしつつ、情報が古かったので自前でサンプルを作成しました）

スプレッドシートで重い数式を書いても表示に時間がかかるくらいですが、Notionだとそもそも結果が出なくなってスキーマから考え直すことになったりします。DBのテーブル設計に慣れていない方にとっては厄介かもしれません。

今回ご紹介した機能一覧の実装であれば、機能のツリーが7階層までは正常に動作しますが、8階層目を作るとカバレッジの計算に失敗しました。これだけ作れれば実用上問題はないかなと思います。ただし実装方法によっては2〜3階層でエラーということも十分ありますから、このあたりの制約は頭に入れておく必要があるでしょう。

# おわりに

テストケースと機能一覧をスプレッドシートからNotionに移行したキッカケと、Notionいいよって話と、実際にこういう設計のもとでNotionのDB設計をしたよ、という話をしました。QAだけではなく、PdMの方にも、開発エンジニアの方にも参考になれば嬉しいです。