概要
過去に pytest で monkeypatch を当てるテクニックを紹介しました
今回は pytest でテストのカバレッジを表示する方法を初回します
環境
- macOS 10.15.5
- Python 3.8.3
- pytest 6.0.1
- pytest-cov 2.10.1
使用するコード
vim user.py
from http.client import HTTPSConnection
class User():
FAVORITE_FRAMEWORKS = {
"ruby": "sinatra",
"swift": "spritekit",
"python": "flask"
}
def __init__(self, name, age):
self.name = name
self.age = age
def hello(self):
return("%s,%i" % (self.name, self.age))
def access(self):
con = HTTPSConnection("kaka-request-dumper.herokuapp.com")
con.request('GET', '/')
res = con.getresponse()
return res.read().decode()
vim test_user.py
import sys
from user import User
def test_hello(monkeypatch):
monkeypatch.setattr(User, "hello", lambda self: "hawksnowlog,5")
u = User("hawksnowlog", 10)
assert(u.hello() == "hawksnowlog,5")
def test_access(monkeypatch):
def mock_return(self):
return '{"key":"value"}'
monkeypatch.setattr(User, "access", mock_return)
u = User("hawksnowlog", 10)
assert(u.access() == '{"key":"value"}')
def test_langs(monkeypatch):
monkeypatch.setitem(User.FAVORITE_FRAMEWORKS, "ruby", "rails")
assert(User.FAVORITE_FRAMEWORKS["ruby"] == "rails")
def test_syspath(monkeypatch):
monkeypatch.syspath_prepend("hoge")
assert(sys.path[0] == "hoge")
pytest-cov のインストール
pytest-cov
という pytest のプラグインがあるのでこれを使います
pipenv install pytest-cov
テスト実行
とりあえずコンソールにカバレッジを表示するだけであれば --cov
を付与するだけです
値はソースがあるプロジェクトのパスになります
pipenv run pytest --cov=.
結果は .coverage
という SQLite 形式のファイルが出力されます
テスト結果を HTML で出力する
HTML ファイルで出力する場合には --cov-report=html
を使います
pipenv run pytest --cov=. --cov-report=html
open htmlcov/index.html
htmlcov/index.html
というファイルを開くと結果が確認できます
以下のような感じでまだテストしていないところを確認するのに便利です
テスト用のコンフィグファイルを作成する
オプションで指定せず設定ファイルにテストのルールなどをあらかじめ記載しておくこともできます
例えば HTML 結果の出力先を変更したい場合には以下のようにします
vim .coveragerc
[html]
directory = coverage_html_report
pipenv run pytest --cov=. --cov-report=html
カバレッジを上げるコツ
monkeypatch を使ったテストを書いているとその部分のコードは通らないことになるのでカバレッジは上がりません
monkeypatch を使ってカバレッジを上げるポイントとしては monkeypatch する関数などは pypi からインストールしたライブラリの関数にしましょう
例えばサンプルコードで access
関数のカバレッジを上げたい場合は access
関数をパッチするのではなく HTTPSConnection
をパッチします
def test_access(monkeypatch):
class DummyHTTPResponse:
def __init__(self):
pass
def read(self):
return b'{"key":"value"}'
class DummyHTTPSconnection:
def __init__(self):
pass
def request(self, method, path):
return None
def getresponse(self):
return DummyHTTPResponse()
monkeypatch.setattr(HTTPSConnection, "request", DummyHTTPSconnection.request)
monkeypatch.setattr(HTTPSConnection, "getresponse", DummyHTTPSconnection.getresponse)
u = User("hawksnowlog", 10)
assert(u.access() == '{"key":"value"}')
HTTPSConnection
で使用している関数だけにパッチを当てれば OK です
return がオブジェクトの場合などはダミー用のクラスを作成してそのダミー用クラスのオブジェクトを返すようにします
そうすることで http.client
側のライブラリの実体ではなくダミー用の関数がコールされるためテストもちゃんと通ることになりカバレッジも下がらずに済みます
最後に
pytest-cov
を使ってカバレッジを表示する方法を紹介しました
monkeypatch
と組み合わせて使うことが多いと思いますがその場合はちゃんとパッチを当てる箇所を考えましょう
闇雲にパッチを当ててもカバレッジが上がらないので少しコツと経験感的なものが必要になりそうです
0 件のコメント:
コメントを投稿