一覧SE-06-3 · 品質測定とレビュー

コードレビューと欠陥の分析

差分の指摘を再現条件と期待結果で記述し、品質の数値を集計対象と観測条件付きで説明します。

説明

レビューでは「ここが気になる」という感想だけでなく、どの入力で何が起き、要求とどう違うかを示すと修正を確認できます。品質指標も、欠陥の件数だけでなく、観測期間・重複・対象版・分母をそろえて読む必要があります。

一覧から最大件数を取り出す関数の変更案を読み、1件多く返す問題を試験にします。後半では固定の欠陥記録を集計し、重複報告や旧版由来の欠陥を含む数と、対象版の変更量あたりの数を比較します。

差分の指摘を再現条件と期待結果で記述し、品質の数値を集計対象と観測条件付きで説明します。

1変更の目的と維持する仕様

変更案は、二段のスライスを一段へまとめるものです。返す件数は最大limit件という仕様を維持します。

cat request.txt変更の目的と維持する条件を読む diff -u抽出式の差分を確認する -L page-old.py -L page.py page-old.py page.py

新しい終了位置はoffset+limit+1です。Pythonのスライスは終了位置を含まないため、1を足す必要があるかを具体的な入力で確認します。

2既存の短い入力では成功する

既存の試験は、2件のリストから最大10件を取る例です。

python3 run_tests.py test_page.Existing既存の短いリストを試す

2件しかないので、終了位置が1大きくても結果は同じです。既存試験の成功は、この変更で最大件数が守られることを十分に確認していません。

3入力と実際の結果を示す

5件のリストにlimit=3を指定します。

python3 -c "from page import page; print(page(list('abcde'),0,3)5件から最大3件を取得する)"

a・b・c・dの4件が返ります。最大3件という仕様との差を、再現できる短い入力で示せました。

4指摘を再現可能な形で残す

入力、期待結果、実際の結果、原因、修正後の確認方法をまとめた指摘を読みます。

cat comment.txtレビュー指摘の根拠を読む python3 run_tests.py test_page.Regression指摘を再現するケースを実行する

上限、途中からの取得、limit=0の3件で失敗します。コードの好みではなく、仕様から外れる条件を示したため、修正したかどうかも同じ試験で確認できます。

5修正後に既存と追加を再試験

終了位置から余分な1を除いた案を反映します。

cp page-fixed.py page.py終了位置を修正する python3 run_tests.py test_page.Existing test_page.Regression既存と追加のケースを確認する

4件が成功します。この入力範囲では、変更前の振舞いと仕様を維持できています。対象外の入力や性能まで確認した結果ではありません。

6欠陥報告の母集団を確認

別の固定資料として、発見日、混入した版、重複先を持つ欠陥一覧と、版ごとの変更行数・試験時間を読みます。

cat bugs.csv発見日・対象版・重複先を読む cat releases.csv変更量と試験時間を読む

B3はB1の重複報告、B2はv1で混入した欠陥です。v2について集計する場合でも、「v2期間に報告された件数」と「v2で混入した固有欠陥数」は同じではありません。 試験時間は版ごとの総記録で、後のコマンドが指定する期間内の時間ではありません。

7期間と混入版を指定して集計

11月1日以上、8日未満を観測期間とし、v2で混入した欠陥を集計します。KLOCは1000行で、分母はv2の変更2000行です。

python3 metrics.py --start 2026-11-01 --end 2026-11-08開始日を含み終了日を含まない期間 --introduced v2v2で混入した固有欠陥を対象にする

報告はB1・B2・B3の3件、重複除去後は2件、v2で混入したものはB1の1件です。変更量2 KLOCで割ると0.5件/KLOCになります。報告3件をそのまま同じ分母で割ると別の指標になります。

8観測期間を延ばすと値が変わる

終了日を11月10日未満まで延ばします。コードの変更量は同じままです。

python3 metrics.py --start 2026-11-01 --end 2026-11-10観測期間を延ばして再集計する --introduced v2

B4とB5が加わり、v2由来の固有欠陥は3件、1.5件/KLOCになります。数値の上昇だけでコードがその日に悪化したとはいえません。観測期間が長くなり、発見した件数が増えています。試験量や検出方法もそろえずに、版や担当者の品質を単純比較できません。

まとめ

レビューでは対象箇所と再現入力、期待・実際の結果を示し、修正後に同じ条件で確認します。

欠陥数は重複、混入版、観測期間によって変わります。分母が変更行数か全体行数かも明示します。

観測期間や試験量が異なる指標は、数値だけを比べて品質の優劣に結び付けません。

操作履歴と解説を振り返れます。

シェル / Python 3

1
cat request.txt diff -u -L page-old.py -L page.py page-old.py page.py
変更案: 一覧の抽出を1回のスライスにまとめる。
維持する仕様: offset件を飛ばし、最大limit件を返す。
この関数の入力: offsetとlimitは0以上の整数、itemsはリスト。
--- page-old.py
+++ page.py
@@ -1,2 +1,2 @@
 def page(items,offset,limit):
-    return items[offset:][:limit]
+    return items[offset:offset+limit+1]
2
python3 run_tests.py test_page.Existing
PASS test_page.Existing.test_short_list
tests=1 failures=0 errors=0
3
python3 -c "from page import page; print(page(list('abcde'),0,3))"
['a', 'b', 'c', 'd']
4
cat comment.txt python3 run_tests.py test_page.Regression
対象: page.py の終了位置の計算。
再現: items=[a,b,c,d,e], offset=0, limit=3。
期待: [a,b,c]。変更案の結果: [a,b,c,d]。
原因: スライスの終了位置は含まれないため、+1すると1件多くなる。
提案: 終了位置をoffset+limitとし、上限・途中開始・limit=0の試験を追加する。
FAIL test_page.Regression.test_limit: Lists differ: ['a', 'b', 'c', 'd'] != ['a', 'b', 'c']

First list contains 1 additional elements.
First extra element 3:
'd'

- ['a', 'b', 'c', 'd']
?               -----

+ ['a', 'b', 'c']
FAIL test_page.Regression.test_offset: Lists differ: ['c', 'd', 'e'] != ['c', 'd']

First list contains 1 additional elements.
First extra element 2:
'e'

- ['c', 'd', 'e']
?          -----

+ ['c', 'd']
FAIL test_page.Regression.test_zero: Lists differ: ['a'] != []

First list contains 1 additional elements.
First extra element 0:
'a'

- ['a']
+ []
tests=3 failures=3 errors=0
5
cp page-fixed.py page.py python3 run_tests.py test_page.Existing test_page.Regression
PASS test_page.Existing.test_short_list
PASS test_page.Regression.test_limit
PASS test_page.Regression.test_offset
PASS test_page.Regression.test_zero
tests=4 failures=0 errors=0
6
cat bugs.csv cat releases.csv
id,found_date,introduced,duplicate_of
B1,2026-11-02,v2,
B2,2026-11-03,v1,
B3,2026-11-04,v2,B1
B4,2026-11-08,v2,
B5,2026-11-09,v2,
release,changed_lines,test_hours
v1,1000,20
v2,2000,100
7
python3 metrics.py --start 2026-11-01 --end 2026-11-08 --introduced v2
reported=B1,B2,B3
unique=B1,B2
introduced_in_release=B1
changed_KLOC=2 defects_per_KLOC=0.5 test_hours=100
8
python3 metrics.py --start 2026-11-01 --end 2026-11-10 --introduced v2
reported=B1,B2,B3,B4,B5
unique=B1,B2,B4,B5
introduced_in_release=B1,B4,B5
changed_KLOC=2 defects_per_KLOC=1.5 test_hours=100

演習完了