戰(zhàn):從 sphinx.ext.coverage 到 grog 測(cè)試示例的完整解析)
文檔開發(fā)工具【免費(fèi)下載鏈接】sphinxThe Sphinx documentation generator項(xiàng)目地址https://gitcode.com/gh_mirrors/sp/sphinx點(diǎn)擊查看免費(fèi)下載Sphinx 自帶的sphinx.ext.coverage擴(kuò)展可以掃描項(xiàng)目中通過 autodoc 或 Python 域記錄的對(duì)象找出那些寫進(jìn)了代碼卻從未被文檔提到的類、函數(shù)和方法并以獨(dú)立構(gòu)建器輸出覆蓋率報(bào)告。本文以倉(cāng)庫(kù)中 tests/roots/test-ext-coverage/index.rst 這一真實(shí)測(cè)試項(xiàng)目為骨架結(jié)合 coverage 擴(kuò)展源碼 與對(duì)應(yīng)測(cè)試用例完整講解覆蓋率構(gòu)建器的啟用方式、全部配置項(xiàng)、忽略規(guī)則的作用機(jī)制以及如何讀懂它生成的python.txt/c.txt報(bào)告幫助你直接在自己項(xiàng)目中復(fù)現(xiàn)這套文檔缺失檢測(cè)流程。從測(cè)試根目錄讀懂 coverage 擴(kuò)展的典型用法Sphinx 倉(cāng)庫(kù)的測(cè)試體系中每個(gè)tests/roots/下的目錄都是一個(gè)獨(dú)立的迷你文檔項(xiàng)目。tests/roots/test-ext-coverage 專為驗(yàn)證sphinx.ext.coverage的忽略規(guī)則而設(shè)計(jì)其結(jié)構(gòu)非常精簡(jiǎn)tests/roots/test-ext-coverage/ ├── conf.py ├── index.rst └── grog/ ├── __init__.py ├── coverage_ignored.py ├── coverage_missing.py └── coverage_not_ignored.py其中 index.rst 全文只有兩個(gè)automodule指令.. automodule:: grog.coverage_ignored :members: .. automodule:: grog.coverage_not_ignored :members:也就是說這個(gè)測(cè)試項(xiàng)目通過 autodoc 只正式記錄了grog包下的兩個(gè)模塊而grog.coverage_missing模塊雖然存在卻沒有被任何automodule/py:module指令提及——它正是用來驗(yàn)證覆蓋率構(gòu)建器能否發(fā)現(xiàn)被文檔遺漏的模塊的靶子。這就是 coverage 擴(kuò)展最核心的場(chǎng)景文檔寫了什么、源碼里有什么兩者之間的差集就是未文檔化對(duì)象。配套的 conf.py 給出了啟用該擴(kuò)展的最小配置import sys from pathlib import Path sys.path.insert(0, str(Path.cwd().resolve())) extensions [sphinx.ext.autodoc, sphinx.ext.coverage] coverage_modules [ grog, ] coverage_ignore_pyobjects [ r^grog\.coverage_ignored(\..*)?$, r\.Ignored$, r\.Documented\.ignored\d$, ]這個(gè)配置里有三個(gè)關(guān)鍵點(diǎn)值得逐一拆解sys.path調(diào)整coverage 構(gòu)建器會(huì)真正import目標(biāo)模塊因此必須讓 Sphinx 進(jìn)程能通過sys.path找到它們官方文檔 doc/usage/extensions/coverage.rst 中也明確提示了這一點(diǎn)。extensions同時(shí)啟用了sphinx.ext.autodoc與sphinx.ext.coverage前者讓automodule指令生效并產(chǎn)生已文檔化對(duì)象記錄后者負(fù)責(zé)掃描源碼并對(duì)比出未文檔化對(duì)象。coverage_ignore_pyobjects定義了三條正則用于把有意不寫文檔的對(duì)象從報(bào)告中剔除——這正是本測(cè)試項(xiàng)目的驗(yàn)證重點(diǎn)。CoverageBuildercoverage 構(gòu)建器的工作原理啟用方式與普通 HTML/PDF 構(gòu)建器不同sphinx.ext.coverage不產(chǎn)生可瀏覽的頁面而是通過sphinx-build -M coverage在_build/coverage目錄下生成文本報(bào)告。它的構(gòu)建器類CoverageBuilder定義在 sphinx/ext/coverage.py在擴(kuò)展的setup()中通過app.add_builder(CoverageBuilder)注冊(cè)sphinx/ext/coverage.py。構(gòu)建器名稱coverage與命令行的對(duì)應(yīng)關(guān)系為sphinx-build -M coverage sourcedir builddir構(gòu)建結(jié)束后builddir/coverage目錄下會(huì)產(chǎn)出三類文件文件內(nèi)容python.txt未文檔化的 Python 對(duì)象清單函數(shù)、類、缺失方法及統(tǒng)計(jì)表c.txt未文檔化的 C API 元素清單undoc.pickle序列化后的全部未文檔化/已文檔化數(shù)據(jù)供后續(xù)程序化分析見 sphinx/ext/coverage.py從CoverageBuilder.epilogsphinx/ext/coverage.py可以看到構(gòu)建完成時(shí)會(huì)輸出提示Testing of coverage in the sources finished, look at the results in builddir/coverage/python.txt.一次構(gòu)建的執(zhí)行流程write_documents()sphinx/ext/coverage.py是覆蓋率構(gòu)建的主入口內(nèi)部順序執(zhí)行四個(gè)步驟build_py_coverage()掃描 Python 模塊產(chǎn)出未文檔化對(duì)象字典write_py_coverage()把結(jié)果寫入python.txtbuild_c_coverage()掃描 C 頭文件產(chǎn)出未文檔化 C API 元素write_c_coverage()把結(jié)果寫入c.txt。Python 側(cè)掃描build_py_coverage()的核心邏輯Python 側(cè)掃描的邏輯sphinx/ext/coverage.py大致如下從self.env.domaindata[py][objects]和[modules]取回文檔樹中所有已出現(xiàn)的 Python 對(duì)象與模塊——這些記錄正是由automodule、py:module、py:function等指令在解析階段寫入環(huán)境的調(diào)用_determine_py_coverage_modules()sphinx/ext/coverage.py確定要檢查哪些模塊這一步?jīng)Q定了兩種工作模式見下文對(duì)每個(gè)模塊執(zhí)行inspect.getmembers(mod)逐成員過濾以下劃線開頭的名字、無法歸屬到本模塊的對(duì)象obj.__module__ ! mod_name、被coverage_ignore_pyobjects匹配的對(duì)象都會(huì)被跳過對(duì)函數(shù)用inspect.isfunction、對(duì)類用inspect.isclass分類再對(duì)比已在文檔中出現(xiàn)的seen_objects凡是在源碼中存在卻不在文檔中的計(jì)入py_undoc對(duì)已文檔化的類還會(huì)遍歷其dir()中的方法/函數(shù)屬性找出類寫了文檔、方法沒寫的缺口記錄為classes[class_name] [缺失的方法名]。關(guān)于_determine_py_coverage_modules()源碼 docstringsphinx/ext/coverage.py明確描述了兩種模式不配置coverage_modules只檢查文檔樹中出現(xiàn)過的模塊。此時(shí)只能發(fā)現(xiàn)這些模塊內(nèi)的缺失對(duì)象但無法發(fā)現(xiàn)整個(gè)模塊都沒被文檔提到的情況配置coverage_modules遞歸導(dǎo)入指定包及其所有子包/子模塊_load_modules使用pkgutil.iter_modules遍歷見 sphinx/ext/coverage.py此時(shí)既能發(fā)現(xiàn)缺失對(duì)象也能發(fā)現(xiàn)模塊級(jí)遺漏。如果文檔中有模塊不在coverage_modules里或coverage_modules里有模塊從未被文檔化構(gòu)建器會(huì)輸出警告但繼續(xù)執(zhí)行sphinx/ext/coverage.py。測(cè)試項(xiàng)目 conf.py 配置了coverage_modules [grog]因此grog.coverage_missing這個(gè)既在源碼中、又不在文檔中的模塊會(huì)被發(fā)現(xiàn)這正是該測(cè)試能驗(yàn)證模塊級(jí)遺漏檢測(cè)的原因。C 側(cè)掃描build_c_coverage()的核心邏輯C API 的掃描sphinx/ext/coverage.py機(jī)制不同但思路一致先收集c域中所有已文檔化的 C 對(duì)象self.env.domains.c_domain.get_objects()遍歷coverage_c_path匹配到的每個(gè)頭文件逐行用coverage_c_regexes中的正則去匹配提取對(duì)象名若該名字未出現(xiàn)在 C 域文檔中則記錄為(類型, 名字)元組寫入c.txt。配置項(xiàng)全覽讓覆蓋率報(bào)告精準(zhǔn)可用coverage擴(kuò)展通過app.add_config_value()注冊(cè)了 13 個(gè)配置項(xiàng)sphinx/ext/coverage.py官方文檔 doc/usage/extensions/coverage.rst 對(duì)其有完整說明。下面按用途分組列出并補(bǔ)充默認(rèn)值與類型Python 側(cè)配置配置項(xiàng)類型默認(rèn)值作用coverage_moduleslist/tuple of str()指定要檢查的包/模塊列表啟用模塊級(jí)遺漏檢測(cè)7.4 版本加入coverage_ignore_moduleslist/tuple of str[]匹配完整模塊路徑的正則列表命中的模塊整個(gè)跳過coverage_ignore_functionslist/tuple of str[]匹配函數(shù)名的正則列表命中的函數(shù)跳過coverage_ignore_classeslist/tuple of str[]匹配類名的正則列表命中的類跳過coverage_ignore_pyobjectslist/tuple of str[]匹配任意 Python 對(duì)象完整導(dǎo)入路徑的正則列表2.1 版本加入這些正則使用 Python 的re語法在構(gòu)建器init()階段通過compile_regex_list()統(tǒng)一編譯sphinx/ext/coverage.py無效正則會(huì)在日志中輸出invalid regex ... in 配置項(xiàng)名警告sphinx/ext/coverage.py。C 側(cè)配置配置項(xiàng)類型默認(rèn)值作用coverage_c_pathlist/tuple of str[]相對(duì)于源目錄的 C 頭文件 glob 模式列表用于定位待檢查的.h文件coverage_c_regexesdict[str, str]{}每個(gè)條目將對(duì)象類型名映射到一條正則正則的第一個(gè)捕獲組即對(duì)象名coverage_ignore_c_itemsdict[str, list of str]{}按對(duì)象類型給出正則列表命中的 C 對(duì)象不計(jì)入缺失報(bào)告C 側(cè)的路徑、正則同樣在init()中預(yù)處理sphinx/ext/coverage.py。報(bào)告輸出配置配置項(xiàng)類型默認(rèn)值作用coverage_write_headlineboolTrue設(shè)為False時(shí)不寫報(bào)告開頭的標(biāo)題行1.1 版本加入coverage_skip_undoc_in_sourceboolFalse跳過源碼中本身就沒有 docstring 的對(duì)象1.1 版本加入coverage_show_missing_itemsboolFalse除了寫入報(bào)告文件還把缺失對(duì)象打印到 stdout / 日志3.1 版本加入coverage_statistics_to_reportboolTrue把統(tǒng)計(jì)表格寫入報(bào)告文件7.2 版本加入coverage_statistics_to_stdoutboolFalse把統(tǒng)計(jì)表格打印到標(biāo)準(zhǔn)輸出7.2 版本加入注意默認(rèn)值與_to_report相反忽略規(guī)則實(shí)戰(zhàn)test-ext-coverage 的三種正則模式回到測(cè)試項(xiàng)目conf.py 中的coverage_ignore_pyobjects三條正則分別演示了三種常見需求coverage_ignore_pyobjects [ r^grog\.coverage_ignored(\..*)?$, # 模式一忽略整個(gè)模塊 r\.Ignored$, # 模式二忽略所有名為 Ignored 的類 r\.Documented\.ignored\d$, # 模式三忽略特定類的特定方法 ]結(jié)合三個(gè)grog子模塊的源碼內(nèi)容coverage_ignored.py、coverage_not_ignored.py、coverage_missing.py逐一驗(yàn)證模式一匹配grog.coverage_ignored及其所有子對(duì)象(\..*)?捕獲后綴。因此即使index.rst通過automodule :members:記錄了該模塊它內(nèi)部的Documented.ignored1、Documented.ignored2、NotIgnored等對(duì)象也不會(huì)進(jìn)入報(bào)告——盡管它們并未被文檔提及。模式二匹配所有以.Ignored結(jié)尾的完整路徑因此兩個(gè)模塊中的Ignored類都被排除。模式三匹配Documented.ignored1/Documented.ignored2這類方法路徑因此這兩個(gè)有意不寫文檔的方法不會(huì)計(jì)入缺失。最終只有g(shù)rog.coverage_not_ignored模塊中的Documented.not_ignored1、not_ignored2和NotIgnored類會(huì)暴露為未文檔化對(duì)象。測(cè)試用例 tests/test_extensions/test_ext_coverage.py 對(duì)這次構(gòu)建的python.txt做了逐字符斷言其統(tǒng)計(jì)表原文如下--------------------------------------------------- | Module | Coverage | Undocumented | | grog | 100.00% | 0 | --------------------------------------------------- | grog.coverage_missing | 100.00% | 0 | --------------------------------------------------- | grog.coverage_not_ignored | 0.00% | 2 | --------------------------------------------------- | TOTAL | 0.00% | 2 | ---------------------------------------------------報(bào)告主體則精確列出了兩個(gè)缺失對(duì)象grog.coverage_missing --------------------- Classes: * Missing grog.coverage_not_ignored ------------------------- Classes: * Documented -- missing methods: - not_ignored1 - not_ignored2 * NotIgnored這份輸出同時(shí)證明了兩個(gè)事實(shí)grog.coverage_missing模塊因從未出現(xiàn)在文檔中而被標(biāo)記為模塊級(jí)遺漏而grog.coverage_not_ignored中的Documented類雖然被automodule記錄但其方法not_ignored1/not_ignored2仍未文檔化。注意測(cè)試斷言的統(tǒng)計(jì)表中兩行 Coverage 均為 100.00%、TOTAL 為 0.00%這是因?yàn)楦采w率百分比按模塊分別計(jì)算、而TOTAL行取的是整體交集分母理解這一點(diǎn)有助于讀懂真實(shí)項(xiàng)目中的統(tǒng)計(jì)數(shù)字。報(bào)告結(jié)構(gòu)解讀與進(jìn)階輸出選項(xiàng)python.txt的完整結(jié)構(gòu)write_py_coverage()sphinx/ext/coverage.py決定了報(bào)告文件的內(nèi)容布局從上到下依次為標(biāo)題Undocumented Python objects可由coverage_write_headline關(guān)閉Statistics 統(tǒng)計(jì)表由coverage_statistics_to_report控制表格由_write_py_statistics()生成見 sphinx/ext/coverage.py按模塊名排序的未文檔化對(duì)象明細(xì)Functions:段模塊級(jí)未文檔化函數(shù)逐行以* 函數(shù)名列出Classes:段未文檔化類逐行列出對(duì)于類已文檔化但方法缺失的情況輸出* 類名 -- missing methods:后逐行縮進(jìn)列出缺失方法名Modules that failed to import段無法 import 的模塊及其異常信息。_write_py_statistics()中覆蓋率的計(jì)算公式為模塊覆蓋率 100.0 * 已文檔化對(duì)象數(shù) / (已文檔化對(duì)象數(shù) 未文檔化對(duì)象數(shù))該模塊沒有發(fā)現(xiàn)任何對(duì)象時(shí)按 100% 處理sphinx/ext/coverage.py。表頭行使用分隔、數(shù)據(jù)行使用-分隔格式與測(cè)試斷言完全一致。讓缺失對(duì)象直接出現(xiàn)在構(gòu)建輸出中默認(rèn)情況下未文檔化對(duì)象只寫入報(bào)告文件構(gòu)建過程中不會(huì)有任何提示。設(shè)置coverage_show_missing_items True后構(gòu)建時(shí)會(huì)同步把缺失對(duì)象打印出來默認(rèn)有進(jìn)度顯示時(shí)使用彩色info日志格式如undocumented py function raises - in module autodoc_target使用-q安靜模式verbosity 0時(shí)改用warning日志格式如undocumented python function: autodoc_target :: raises。測(cè)試用例 test_show_missing_items 與 test_show_missing_items_quiet 分別驗(yàn)證了這兩種輸出路徑同時(shí)覆蓋了 Python 函數(shù)、類、方法以及 C API 元素如undocumented c api: Py_SphinxTest [function]四種類型的提示。C 側(cè)報(bào)告c.txt的結(jié)構(gòu)與python.txt類似先寫Undocumented C API elements標(biāo)題再按頭文件分組列出未文檔化元素每行格式為* 名字 [類型]sphinx/ext/coverage.py。在真實(shí)項(xiàng)目中落地完整配置示例與注意事項(xiàng)將上述內(nèi)容整合一個(gè)可直接照搬的項(xiàng)目級(jí)配置如下在conf.py中extensions [ sphinx.ext.autodoc, sphinx.ext.coverage, ] # 指定要遞歸檢查的包不設(shè)置則只檢查文檔中出現(xiàn)過的模塊 coverage_modules [my_package] # 忽略規(guī)則可分別針對(duì)模塊、函數(shù)、類、任意對(duì)象編寫正則 coverage_ignore_modules [rmy_package\.internal] coverage_ignore_functions [r^_] coverage_ignore_classes [] coverage_ignore_pyobjects [r\.Deprecated$] # C API 檢查可選 coverage_c_path [include/*.h] coverage_c_regexes {function: r^\w\s(\w)\s*\(} coverage_ignore_c_items {function: [r^internal_]} # 報(bào)告輸出控制 coverage_show_missing_items True # 構(gòu)建時(shí)直接打印缺失對(duì)象 coverage_skip_undoc_in_source False # True 則跳過源碼中無 docstring 的對(duì)象 coverage_statistics_to_stdout True # 統(tǒng)計(jì)表同時(shí)輸出到 stdout coverage_statistics_to_report True # 統(tǒng)計(jì)表寫入報(bào)告 coverage_write_headline True # False 則不寫標(biāo)題行運(yùn)行方式sphinx-build -M coverage source _build然后查看_build/coverage/python.txt與_build/coverage/c.txt。結(jié)合源碼與官方文檔doc/usage/extensions/coverage.rst使用時(shí)有幾點(diǎn)需要注意模塊導(dǎo)入副作用coverage 構(gòu)建器會(huì)真實(shí)import被檢查的模塊。如果模塊在導(dǎo)入時(shí)執(zhí)行了副作用代碼如發(fā)請(qǐng)求、寫文件這些代碼會(huì)在sphinx-build運(yùn)行期間被執(zhí)行。對(duì)于腳本類模塊務(wù)必用if __name__ __main__:保護(hù)入口這是官方文檔中明確給出的警告。sys.path可見性被檢查的模塊必須能被 Python 解釋器 import 到必要時(shí)像測(cè)試項(xiàng)目的 conf.py 一樣在sys.path中插入項(xiàng)目根目錄。模塊級(jí)遺漏需要顯式配置只有設(shè)置coverage_modules后才能發(fā)現(xiàn)整個(gè)模塊都沒出現(xiàn)在文檔中的遺漏不設(shè)置時(shí)只能發(fā)現(xiàn)已文檔化模塊內(nèi)部的缺失對(duì)象。忽略規(guī)則使用正則匹配coverage_ignore_pyobjects等配置匹配的是對(duì)象完整導(dǎo)入路徑如grog.coverage_ignored.Documented.ignored1的任意部分^/$/\d等re語法全部可用且匹配使用search語義見 sphinx/ext/coverage.py因此\.Ignored$這類錨定寫法可以精確命中類名結(jié)尾。小結(jié)tests/roots/test-ext-coverage/index.rst雖然只有六行但它背后是sphinx.ext.coverage一整套源碼對(duì)照文檔的掃描機(jī)制CoverageBuilder以python.txt/c.txt/undoc.pickle三種形式輸出結(jié)果13 個(gè)配置項(xiàng)覆蓋了模塊級(jí)掃描、正則忽略、統(tǒng)計(jì)表格與日志輸出等全部需求。借助 conf.py 中的三條忽略規(guī)則和 test_ext_coverage.py 的逐字節(jié)斷言你可以清晰地推演任意對(duì)象被納入或排除的判定路徑并把這套能力直接復(fù)用到自己的文檔項(xiàng)目中——讓寫了代碼卻忘了寫文檔的缺口在每次構(gòu)建時(shí)自動(dòng)暴露出來。贊分享文檔開發(fā)工具【免費(fèi)下載鏈接】sphinxThe Sphinx documentation generator項(xiàng)目地址https://gitcode.com/gh_mirrors/sp/sphinx點(diǎn)擊查看免費(fèi)下載相關(guān)推薦flexivit_base.300ep_in21k vs 傳統(tǒng)ViT19.4 GMACs如何實(shí)現(xiàn)更優(yōu)性能flexivit_base.300ep_in21k vs 傳統(tǒng)ViT19.4 GMACs如何實(shí)現(xiàn)更優(yōu)性能 在計(jì)算機(jī)視覺領(lǐng)域視覺TransformerViECC 測(cè)試覆蓋率實(shí)戰(zhàn)指南/test-coverage 命令從覆蓋率分析到缺口測(cè)試生成的完整工作流ECC 測(cè)試覆蓋率實(shí)戰(zhàn)指南/test coverage 命令從覆蓋率分析到缺口測(cè)試生成的完整工作流 本文聚焦 ECCEverything Claude Co人工智能AI 技能AI 插件AI 評(píng)測(cè)Agent 評(píng)測(cè)MCP Clients開發(fā)工具Grafana儀表板深度解析Kubernetes監(jiān)控的高級(jí)功能與最新特性Grafana儀表板深度解析Kubernetes監(jiān)控的高級(jí)功能與最新特性 Kubernetes監(jiān)控是現(xiàn)代云原生運(yùn)維的核心而grafana dashboard上一篇構(gòu)建響應(yīng)式應(yīng)用gh_mirrors/pr/promises事件驅(qū)動(dòng)編程下一篇如何使用DGFraud在5分鐘內(nèi)搭建第一個(gè)欺詐檢測(cè)模型快速入門指南創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考