この投稿では、単体テストの実装、複雑な構成の課題の処理、ReadmeGenie での堅牢なコード カバレッジの導入について順を追って説明します。初期のテスト設計からコミット前フックの設定に至るまで、このプロセスにはコードの品質、信頼性、開発者のワークフローにおけるさまざまな改善が含まれていました。
まず、テストを作成して実行するための主要なフレームワークとして、unittest を選択しました。 Python の組み込み単体テストは、テスト ケースを定義するための構造化されたアプローチを提供し、モックとの統合により、複雑な構成や API 呼び出しのテストに最適です。
tests/ ディレクトリ内のすべてのテスト ファイルを自動的に検出して実行するための専用のテスト ランナー (tests/test_runner.py) を作成しました。
# tests/test_runner.py import unittest if __name__ == "__main__": loader = unittest.TestLoader() suite = loader.discover(start_dir="tests", pattern="test_*.py") runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)
この設定により、python testing/test_runner.py を実行するとすべてのテスト ファイルが自動的にロードされて実行されるため、プロジェクト全体の機能を簡単に検証できます。
ReadmeGenie プロジェクトでは、いくつかのコンポーネントの包括的なテストが必要でした。
各テスト ファイルは、テストするモジュールに応じて名前が付けられ (例: 引数解析の場合は test_parse_arg.py、モデル関数の場合は test_model.py)、明確で保守可能な構造が保証されます。
test_loadConfig.py のセットアップは、このプロジェクトで最も困難な部分であることが判明しました。最初は、環境変数とファイル パスのチェックに関連する永続的な問題に遭遇しました。 load_config() はさまざまな構成ソース (環境変数、.env ファイル、JSON、TOML ファイルなど) を処理することを目的としているため、テストではこれらの環境を正確にシミュレートするために広範なモックが必要でした。
関係する主な問題:
環境変数の競合: 既存の環境変数がモック値と干渉することがありました。 @patch.dict("os.environ", {}, clear=True) を使用して、テスト スコープ内の環境変数をクリアして、一貫した結果を確保しました。
ファイル パス チェック:load_config() はファイルの存在をチェックするため、os.path.exists を使用して、構成ファイルが存在するか存在しないシナリオをシミュレートしました。
open と toml.load のモック: これらには、構成ファイルが欠落している、空である、または設定されている場合を処理するための正確なモックが必要でした。 toml.load にパッチを適用したmock_openを使用して、各状況を効果的にシミュレートしました。
これらの問題を解決した後、test_loadConfig.py は 3 つの主要なシナリオをカバーするようになりました。
test_loadConfig.py の最終バージョンは次のとおりです:
# tests/test_runner.py import unittest if __name__ == "__main__": loader = unittest.TestLoader() suite = loader.discover(start_dir="tests", pattern="test_*.py") runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)
テストを実施した後、coverage.py を使用してカバレッジの測定と改善に重点を置きました。 80% のしきい値を設定することで、コードのすべての重要な部分が確実にテストされることを目指しました。
pyproject.toml で次の設定を使用して Coverage.py を構成しました:
import unittest from unittest.mock import mock_open, patch from loadConfig import load_config class TestLoadConfig(unittest.TestCase): @patch.dict("os.environ", {}, clear=True) @patch("loadConfig.os.getenv", side_effect=lambda key, default=None: default) @patch("loadConfig.os.path.exists", return_value=False) @patch("builtins.open", new_callable=mock_open, read_data="{}") @patch("loadConfig.toml.load", return_value={}) def test_load_config_empty_file(self, mock_toml_load, mock_open_file, mock_exists, mock_getenv): config = load_config() self.assertEqual(config, {}) @patch.dict("os.environ", {}, clear=True) @patch("loadConfig.os.getenv", side_effect=lambda key, default=None: default) @patch("loadConfig.os.path.exists", return_value=True) @patch("builtins.open", new_callable=mock_open, read_data='{"api_key": "test_key"}') @patch("loadConfig.toml.load", return_value={"api_key": "test_key"}) def test_load_config_with_valid_data(self, mock_toml_load, mock_open_file, mock_exists, mock_getenv): config = load_config() self.assertEqual(config.get("api_key"), "test_key") @patch.dict("os.environ", {}, clear=True) @patch("loadConfig.os.getenv", side_effect=lambda key, default=None: default) @patch("loadConfig.os.path.exists", return_value=False) @patch("builtins.open", side_effect=FileNotFoundError) @patch("loadConfig.toml.load", return_value={}) def test_load_config_file_not_found(self, mock_toml_load, mock_open_file, mock_exists, mock_getenv): config = load_config() self.assertEqual(config, {})
この構成には分岐カバレッジが含まれており、欠落している行が強調表示され、最低 75% のカバレッジしきい値が適用されます。
これを開発ワークフローに統合するために、コミット前フックを追加して、コミットごとにコード カバレッジがチェックされるようにしました。カバレッジが 75% を下回る場合、コミットはブロックされ、続行する前にカバレッジを改善するよう開発者に求められます。
[tool.coverage.run] source = [""] branch = true omit = ["tests/*"] [tool.coverage.report] show_missing = true fail_under = 75
私たちの最近の取材レポートは次のとおりです:
- repo: local hooks: - id: check-coverage name: Check Coverage entry: bash -c "coverage run --source=. -m unittest discover -s tests && coverage report -m --fail-under=75" language: system
一部の領域ではカバレッジが強力ですが (loadConfig.py が 100% であるなど)、models/model.py と readme_genie.py にはまだ改善の余地があります。全体のカバレッジ 85% 以上という目標を達成するには、テストされていないブランチやエッジ ケースに焦点を当てることが重要です。
このプロジェクトは、単体テスト、モック、コード カバレッジについて多くのことを学びました。 test_loadConfig.py のセットアップは特に貴重な経験であり、より深いレベルの構成モックを探求するきっかけになりました。カバレッジの事前コミット フックにより、品質保証の層が追加され、一貫したテスト基準が強制されます。
今後は、エッジケースを追加し、ブランチカバレッジを改善することで、これらのテストをさらに改良することを目指しています。これにより、ReadmeGenie がより堅牢になるだけでなく、将来の開発のための強固な基盤が築かれます。
以上がReadmeGenie での単体テストの実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。