日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Diango博客--25.使用Coverage统计测试覆盖率

發布時間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Diango博客--25.使用Coverage统计测试覆盖率 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1. 前言
  • 2. 安裝 Coverage
  • 3. 簡單配置 Coverage
  • 4. 運行 Coverage
  • 5. 完善 Coverage 配置
  • 6. 生成 HTML 報告
  • 7. 完善單元測試

1. 前言

我們完成了對 blog 應用和 comment 應用這兩個核心 app 的測試。現在我們想知道的是究竟測試效果怎么樣呢?測試充分嗎?測試全面嗎?還有沒有沒有測到的地方呢?

單憑肉眼觀察難以回答上面的問題,接下來我們就借助 Coverage.py,從代碼覆蓋率的角度來檢測一下我們的測試效果究竟如何。

Coverage.py (以下簡稱 Coverage)是 Python 測試界最為流行的一個庫之一,用來統計測試覆蓋率。測試覆蓋率可以從一個角度衡量代碼的質量,覆蓋率越高,說明測試越充分,代碼出現 bug 的幾率也就越小。當然需要注意的是,測試覆蓋率僅僅只是衡量代碼質量的一個角度,即使是 100% 的覆蓋率也不能說代碼就是完美的,沒有 bug 的。

2. 安裝 Coverage

要使用 Coverage,首先當然是安裝它:

$ pipenv install coverage --dev

因為只在開發時才用得到,所以使用 Pipenv 安裝時加 --dev 選項將其標記為開發時的依賴庫。

3. 簡單配置 Coverage

Coverage 支持很多配置選項,為了方便,通常將這些配置寫在名為 .coveragerc 的文件中,Coverage 運行時會從項目根目錄讀取這個配置文件。因此先在項目根目錄創建這個文件并寫入最基本的配置:

[run] branch = True source = . [report] show_missing = True

Coverage 的配置遵循 ini 文件語法。簡單來說就是,[section] 代表一個配置塊,用于組織相關的一組配置。例如這里 [run] 是一個配置塊,[report] 是另一個配置塊,兩個塊下都有相關的一些配置項。配置項的格式為 key = value 。這幾個簡單配置項的含義為:

  • branch = True 是否統計條件語句的分支覆蓋情況。if 條件語句中的判斷通常有 True 和 False 兩種情況,設置 branch = True 后,Coverage 會測量這兩種情況是否都被測試到。
  • source =. 指定需統計的源代碼目錄,這里設置為當前目錄(即項目根目錄)。
  • show_missing = True 在生成的統計報告中顯示未被測試覆蓋到的代碼行號。
  • 4. 運行 Coverage

    簡單配置后,我們就可以來運行 Coverage 了。打開命令行,進入項目根目錄,依次運行下面的命令(注意如果沒有激活python shell 虛擬需使用 pipenv run 讓命令在虛擬環境中執行)。

    首先運行 erase 命令清除上一次的統計信息

    $ pipenv run coverage erase

    manage.py test 運行 django 單元測試,這是這一次用 coverage run 來運行

    $ pipenv run coverage run manage.py test

    生成覆蓋率統計報告

    $ pipenv run coverage report

    覆蓋率統計報告輸出如下:

    Name Stmts Miss Branch BrPart Cover Missing -------------------------------------------------------------------------------------------- _credentials.py 2 2 0 0 0% 1-2 blog\__init__.py 0 0 0 0 100% blog\admin.py 11 0 0 0 100% blog\apps.py 4 0 0 0 100% blog\elasticsearch2_ik_backend.py 8 0 0 0 100% blog\feeds.py 12 0 0 0 100% blog\migrations\0001_initial.py 7 0 0 0 100% blog\migrations\0002_auto_20190711_1802.py 7 0 0 0 100% blog\migrations\0003_auto_20191011_2326.py 4 0 0 0 100% blog\migrations\0004_post_views.py 4 0 0 0 100% blog\migrations\__init__.py 0 0 0 0 100% blog\models.py 62 0 0 0 100% blog\search_indexes.py 8 0 0 0 100% blog\templatetags\__init__.py 0 0 0 0 100% blog\templatetags\blog_extras.py 15 0 0 0 100% blog\tests\__init__.py 0 0 0 0 100% blog\tests\test_models.py 58 0 2 0 100% blog\tests\test_smoke.py 4 0 0 0 100% blog\tests\test_templatetags.py 115 0 2 0 100% blog\tests\test_utils.py 11 0 0 0 100% blog\tests\test_views.py 170 0 8 0 100% blog\urls.py 4 0 0 0 100% blog\utils.py 10 0 2 1 92% 14->16 blog\views.py 40 7 2 0 79% 64-72 blogproject\__init__.py 0 0 0 0 100% blogproject\settings\__init__.py 0 0 0 0 100% blogproject\settings\common.py 22 0 0 0 100% blogproject\settings\local.py 5 0 0 0 100% blogproject\settings\production.py 5 5 0 0 0% 1-8 blogproject\urls.py 4 0 0 0 100% blogproject\wsgi.py 4 4 0 0 0% 10-16 comments\__init__.py 0 0 0 0 100% comments\admin.py 6 0 0 0 100% comments\apps.py 4 0 0 0 100% comments\forms.py 6 0 0 0 100% comments\migrations\0001_initial.py 7 0 0 0 100% comments\migrations\0002_auto_20191011_2326.py 4 0 0 0 100% comments\migrations\__init__.py 0 0 0 0 100% comments\models.py 15 0 0 0 100% comments\templatetags\__init__.py 0 0 0 0 100% comments\templatetags\comments_extras.py 12 0 2 0 100% comments\tests\__init__.py 0 0 0 0 100% comments\tests\base.py 10 0 0 0 100% comments\tests\test_models.py 8 0 0 0 100% comments\tests\test_templatetags.py 57 0 6 0 100% comments\tests\test_views.py 34 0 4 0 100% comments\urls.py 4 0 0 0 100% comments\views.py 17 0 2 0 100% fabfile.py 21 21 0 0 0% 1-43 manage.py 12 2 2 1 79% 11-12, 20->exit scripts\__init__.py 0 0 0 0 100% scripts\fake.py 63 63 14 0 0% 1-106 -------------------------------------------------------------------------------------------- TOTAL 876 104 46 2 87%

    倒數第二列是被統計文件的測試覆蓋率,倒數第一列是未被覆蓋的代碼行號。大部分文件測試覆蓋率為 100%,說明我們的測試還是比較充分的。但從報告結果中我們發現這樣幾個問題:

  • 有一些文件其實并不需要測試,或者并非項目的核心文件(例如使用fabiric部署項目的腳本 fabfile.py,django 的 migrations 文件等),這些文件應該從統計中排除。
  • Coverage 默認顯示全部文件的覆蓋率統計結果,如果文件比較多的話就不好查找非 100% 覆蓋率的文件。畢竟我們的目標是提高代碼覆蓋率,因此已達 100% 覆蓋的代碼文件我們不再關心。我們要做的是找到非 100% 覆蓋率的文件,為其添加缺失的測試。
  • 5. 完善 Coverage 配置

    可以通過添加 Coverage 配置項輕松解決上面 2 個問題。

    在 [run] 配置塊中增加 omit 配置項可以指定排除統計的文件。在 [report] 配置塊中增加 skip_covered 配置項可以指定統計報告中不顯示 100% 覆蓋的文件。

    這是 .coveragerc 最終配置結果,注意我們在 omit 配置項中指定忽略了一些非核心的項目文件:

    [run] branch = True source = . omit =_credentials.pymanage.pyblogproject/settings/*fabfile.pyscripts/fake.py*/migrations/*blogproject\wsgi.py[report] show_missing = True skip_covered = True

    再次按照上一節所說的方式運行 Coverage,最終報告結果如下:

    Name Stmts Miss Branch BrPart Cover Missing ----------------------------------------------------------- blog\utils.py 10 0 2 1 92% 14->16 blog\views.py 40 7 2 0 79% 64-72 ----------------------------------------------------------- TOTAL 709 7 30 1 99%33 files skipped due to complete coverage.

    這個報告指出我們仍有 2 個文件沒有達到 100% 的覆蓋率,我們要做的就是為這兩個文件中未測試的代碼增加單元測試,讓其達到 100% 測試覆蓋率。

    不過在動手寫測試之前,我們要搞清楚哪些代碼沒被測到。命令行報告的最后一列指出了未被測試代碼的行號,但是這樣看著不是很直觀。一種體驗更好的方式是生成 HTML 報告,這樣我們可以直接在 HTML 報告中查看到未被測試到的具體代碼。

    6. 生成 HTML 報告

    coverage report 命令在命令行生成統計報告,而 coverage html 則可以生成 HTML 報告。

    在上一節的基礎上,運行如下命令:

    $ pipenv run coverage html

    運行完成后項目根目錄會多出一個 htmlcov 的文件夾,里面就是測試覆蓋率的 HTML 報告文件。用瀏覽器打開里面的 index.html 文件就可以查看報告結果了:

    主頁和命令行的結果是一樣的,不過我們可以點擊文件名,進入到對這個文件更加具體的統計報告頁面,例如 blog\views.py 結果如下:

    綠色部分代表已覆蓋的代碼,紅色部分代表未覆蓋的代碼。查看文件我們發現,blog\views.py 中未被覆蓋的代碼原來是 Django 博客實現簡單的全文搜索 中的代碼,現在我們已經將搜索替換為 Django Haystack 全文檢索 了,這段代碼也就不需要了,可以直接刪除。

    7. 完善單元測試

    blog\utils.py 的報告結果則表明我們在 Django Haystack 全文檢索與關鍵詞高亮 中自定義的搜索關鍵詞高亮器有一個 if 分支條件未被測試到:

    檢查 blog/tests/test_utils.py 中的測試用例,我們發現只測試了比較短的標題不被截斷,也就是

    if len(text_block) < self.max_length:

    判斷條件為 True,缺失對判斷條件為 False 的測試。所以我們來構造一個新的測試用例測試標題長度超過 max_length (默認值為 200)的情況時會被截斷:

    class HighlighterTestCase(TestCase):def test_highlight(self):# 省略已有代碼 ...highlighter = Highlighter("標題")document = "這是一個長度超過 200 的標題,應該被截斷。" + "HelloDjangoTutorial" * 200self.assertTrue(highlighter.highlight(document).startswith('...<span class="highlighted">標題</span>,應該被截斷。'))

    再次運行 Coverage 生成報告,測試覆蓋率全都 100% 了!

    $ pipenv run coverage erase $ pipenv run coverage run manage.py test $ pipenv run coverage report # 輸出 Name Stmts Miss Branch BrPart Cover Missing --------------------------------------------------- --------------------------------------------------- TOTAL 704 0 28 0 100%

    最后提醒一點,Coverage 運行后可能會在項目目錄下生成一些文件,這些文件并不需要納入版本管理,所以將其加入 .gitignore 文件中,防止被提交到代碼庫:

    htmlcov/ .coverage .coverage.* coverage.xml *.cover

    總結

    以上是生活随笔為你收集整理的Diango博客--25.使用Coverage统计测试覆盖率的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。