コード整形・静的解析・動作テスト
見た目の整形、コード上の問題の検出、要求どおりの結果の確認を、それぞれの出力から判断します。
説明
コードを整形すると表記がそろいますが、変数名の誤りや計算規則まで自動で直るわけではありません。静的解析は実行せずに検出できる問題を探し、動作試験は具体的な入力と期待結果を照合します。
Ruff 0.17.4で、未使用importと未定義名を含む割引関数を調べます。整形後にも指摘が残ること、安全な自動修正で直せる範囲、静的解析を通っても値引き後の切捨て規則に違反する例を確認します。
見た目の整形、コード上の問題の検出、要求どおりの結果の確認を、それぞれの出力から判断します。
1読める形と正しい動作は別
source.pyは10%引きの計算です。仕様は、値引き後の額の1円未満を切り捨てることです。
cat source.py修正前のソースを読む未使用のmathと、amountをamuntと書いた箇所があります。空白の不統一もありますが、それぞれ別の種類の問題です。
2実行せずに問題を検出する
未使用importのF401と、未定義名のF821を選んで解析します。
python3 -m ruff check静的解析を実行する --select F401,F821確認する規則を明示する --output-format concise位置と指摘を簡潔に表示する source.pymathとamuntの2件が指摘されます。行・列の位置が付くので、該当箇所を確認できます。星印の付いた未使用importは、この条件で自動修正の対象です。
3整形してから再解析する
formatterで表記をそろえ、同じ規則で再び解析します。
python3 -m ruff format source.pyソースの表記を整える
cat source.py
python3 -m ruff check --select F401,F821同じ問題が残っているか確認する --output-format concise source.py空行やインデントは整いましたが、指摘は2件のままです。amuntの行番号が移っても、未定義名という問題は残っています。整形は仕様や変数名の意図を推測して修正する機能ではありません。
4自動修正の対象を限定する
未使用importだけを自動修正します。
python3 -m ruff check --select F401 --fix未使用importの規則だけを適用して直す source.py
cat source.py修正後にも残るamuntを確認するmathのimportが削除されました。表示の0 remainingは、ここで選んだF401についての結果です。F821や業務上の要求まで問題がなくなった意味ではありません。
5変数名を直して解析を通す
amountへ直した案を反映します。計算式はまだ浮動小数点数の0.9を掛ける形です。
cp name-fixed.py source.py正しい引数名へ直す
python3 -m ruff check --select F401,F821同じ二規則で再確認する --output-format concise source.pyAll checks passedになります。選んだ静的解析の規則には違反しませんが、値引き後の1円未満を切り捨てる仕様は検査していません。
6仕様の端数処理を試験する
100円と101円の10%引きは、それぞれ90円と90円になることを確認します。
python3 run_tests.py test_discount.Values要求に基づく金額を照合する100円は通りますが、101円では90.9になりFAILです。静的解析は、このアプリの丸め規則を知らないため、数式として有効なamount * 0.9を誤りとして扱いません。
7計算規則を直して両方を確認
整数の円で切り捨てる案との差分を読み、反映します。
diff -u端数処理を含む計算式の差分 -L source.py -L rule-fixed.py source.py rule-fixed.py
cp rule-fixed.py source.py仕様に合わせた計算へ変更する
python3 run_tests.py test_discount.Values金額の動作を確認する
python3 -m ruff check静的な指摘も再確認する --select F401,F821 --output-format concise source.py動作試験2件と静的解析の両方が成功します。複数の検査は代替関係ではなく、それぞれが見つけられる問題を補っています。
まとめ
formatterは表記を整え、linterは選択した規則に基づく問題を検出します。
自動修正後の成功は、実行した規則の範囲で読み取ります。未選択の規則や業務仕様の達成を意味しません。
要求固有の端数処理は、具体的な入力と期待値を持つ動作試験で確認します。
操作履歴と解説を振り返れます。
シェル / Python 3
cat source.pyimport math def discounted( amount ): return amunt*0.9
python3 -m ruff check --select F401,F821 --output-format concise source.pysource.py:1:8: F401 [*] `math` imported but unused source.py:3:9: F821 Undefined name `amunt` Found 2 errors. [*] 1 fixable with `--fix`.
python3 -m ruff format source.py
cat source.py
python3 -m ruff check --select F401,F821 --output-format concise source.py1 file reformatted
import math
def discounted(amount):
return amunt * 0.9
source.py:1:8: F401 [*] `math` imported but unused
source.py:5:12: F821 Undefined name `amunt`
Found 2 errors.
[*] 1 fixable with `--fix`.python3 -m ruff check --select F401 --fix source.py
cat source.pyFound 1 error (1 fixed, 0 remaining).
def discounted(amount):
return amunt * 0.9cp name-fixed.py source.py
python3 -m ruff check --select F401,F821 --output-format concise source.pyAll checks passed!
python3 run_tests.py test_discount.ValuesFAIL test_discount.Values.test_fraction: 90.9 != 90 PASS test_discount.Values.test_hundred tests=2 failures=1 errors=0
diff -u -L source.py -L rule-fixed.py source.py rule-fixed.py
cp rule-fixed.py source.py
python3 run_tests.py test_discount.Values
python3 -m ruff check --select F401,F821 --output-format concise source.py--- source.py +++ rule-fixed.py @@ -1,2 +1,2 @@ def discounted(amount): - return amount * 0.9 + return amount * 90 // 100 PASS test_discount.Values.test_fraction PASS test_discount.Values.test_hundred tests=2 failures=0 errors=0 All checks passed!
演習完了