LoginSignup
0
1

Poetry で pytest

Last updated at Posted at 2023-12-02

pytest の使い方がときどきよくわからなくなるので備忘録。

ディレクトリ構成

  • 単体テストは tests/test_hello.py に記述
  • hello/hello.py で Hello Class を定義
  • hello/main.py で Hello Class インスタンスを作成,say メソッドを実行した際に Hello, World! を print
├── hello
│   ├── __init__.py
│   ├── hello.py
│   └── main.py
├── poetry.lock
├── pyproject.toml
└── tests
    └── test_hello.py

Poetry のインストール

Poetry Installation

curl -sSL https://install.python-poetry.org | python3 -

pyproject.toml

poetry init を実行するか,エディタ等で pyproject.toml を作成します。

pyproject.toml
[tool.poetry]
name = "hello"
version = "0.1.0"
description = "getting started with pytest"
authors = ["Your Name <you@example.com>"]

[tool.poetry.dependencies]
python = "^3.11"
pytest = "^7.4.3"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry.scripts]
hello = "hello.main:main"

poetry init を使った場合は,poetry add pytest も実行する必要があります。

poetry run hello で hello/main.py の main 関数を実行します。
name = "hello" と hello ディレクトリで名前に不整合があると,以下の No module エラーが発生します。

    from hello.hello import Hello
E   ModuleNotFoundError: No module named 'hello'

poetry install / update

poetry install を実行します。

$ poetry install
Updating dependencies
Resolving dependencies... (0.1s)

No dependencies to install or update

Writing lock file

Installing the current project: hello (0.1.0)

テストコードを記述

Hello Class インスタンスを作成,greeting メソッドを実行した際に Hello, World! が返されることを期待します。

test_hello.py
import pytest
from hello.hello import Hello

def test_hello():
    hello = Hello()
    assert hello.greeting == "Hello, World!"

pytest を実行

$ poetry run pytest -v
========================= test session starts ==========================
platform darwin -- Python 3.11.6, pytest-7.4.3, pluggy-1.3.0 -- /Users/foo/Library/Caches/pypoetry/virtualenvs/hello-7y5vTctl-py3.11/bin/python
cachedir: .pytest_cache
rootdir: /Users/foo/lab
collected 0 items / 1 error

================================ ERRORS ================================
_________________ ERROR collecting tests/test_hello.py _________________
ImportError while importing test module '/Users/foo/lab/tests/test_hello.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/opt/homebrew/Cellar/python@3.11/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests/test_hello.py:2: in <module>
    from hello.hello import Hello
E   ImportError: cannot import name 'Hello' from 'hello.hello' (/Users/foo/lab/hello/hello.py)
======================= short test summary info ========================
ERROR tests/test_hello.py
!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!
=========================== 1 error in 0.03s ===========================

まだ何も Class を記述していないので当然テストに失敗します。

Hello Class を記述

以下のように Hello Class を定義します。

hello/hello.py
class Hello:
    def __init__(self):
        self.greeting = "Hello, World!"

    def say(self):
        print(self.greeting)

テストを再実行

$ poetry run pytest -v
========================= test session starts ==========================
platform darwin -- Python 3.11.6, pytest-7.4.3, pluggy-1.3.0 -- /Users/foo/Library/Caches/pypoetry/virtualenvs/hello-7y5vTctl-py3.11/bin/python
cachedir: .pytest_cache
rootdir: /Users/foo/lab
collected 1 item

tests/test_hello.py::test_hello PASSED                           [100%]

========================== 1 passed in 0.00s ===========================

テストをパスしました。

main.py を記述

メインのコードを記述します。お約束の Hello, World! を print するだけです。

hello/main.py
from hello.hello import Hello

def main():
    greeting = Hello()
    greeting.say()

poetry run で期待通りの結果が得られました。

$ poetry run hello
Hello, World!
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1