pytest で ModuleNotFoundError: No module named 'xxx' になる

python で簡単なアプリケーションを作成して test コードを書こうとおもって ``pytest`` を使用したのですが、コンソールから ``pytest`` を実行すると ``ModuleNotFoundError: No module named 'xxx' `` でエラーが発生。いろいろ調べて 2 つの方法でエラーを解消することができたので書き残しておきます。

## 準備

下記のアプリケーションに対してテストコードを書きました。

https://qiita.com/kiyo27/items/d928f65b215d914f1979

テストコードの中身:

```python:tests/test_todo.py
import os
import pytest
from dao.todo import TodoDAO

@pytest.fixture
def todo_instance():
    return TodoDAO()

class TestTodoClass:
    def test_create(self, todo_instance):
        obj = todo_instance.create({'task': 'Build an API'})
        assert 'Build an API' == obj['task']
        assert len(todo_instance.todos) == 1
```

``pytest`` 実行後のエラー内容:

```terminal
_________________________________________ ERROR collecting tests/test_todo.py _________________________________________
ImportError while importing test module 'C:\Users\kiyo27\workspace\python-flask\tests\test_todo.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
    return _bootstrap._gcd_import(name[level:], package, level)
tests\test_todo.py:3: in <module>
    from dao.todo import TodoDAO
E   ModuleNotFoundError: No module named 'dao'
=============================================== short test summary info ===============================================
ERROR tests/test_todo.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
================================================== 1 error in 0.18s ===================================================
(
```

## ``python -m pytest [...]`` で実行

pytest の doc に記載がありました。
https://docs.pytest.org/en/latest/how-to/usage.html#other-ways-of-calling-pytest

``python`` で実行すると、カレントディレクトリが ``sys.path`` に登録されるので、``tests/test_todo.py`` から ``dao`` モジュールが呼び出せています。

``pytest`` 実行:

```terminal
> python -m pytest
================================================= test session starts =================================================
platform win32 -- Python 3.8.10, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: C:\Users\kiyo27\workspace\python-flask, configfile: setup.cfg, testpaths: tests
collected 1 item

tests\test_todo.py .                                                                                             [100%]

================================================== 1 passed in 0.48s ==================================================
(
```

## ``pip install -e .``

こちらは、flask の doc に書いてある方法です。
https://flask.palletsprojects.com/en/2.0.x/testing/

``setup.cfg`` を用意して``pip install -e .`` を実行すると、``pytest`` 時にモジュールが呼び出せるようになります。

```python:setup.cfg
[metadata]
name = todo
version = 1.0.0

[tool:pytest]
testpaths = tests
```

``pytest`` 実行:

```terminal
> pytest -v
================================================= test session starts =================================================
platform win32 -- Python 3.8.10, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- c:\users\kiyo27\workspace\python-flask\.venv\scripts\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\kiyo27\workspace\python-flask, configfile: setup.cfg, testpaths: tests
collected 1 item

tests/test_todo.py::TestTodoClass::test_create PASSED
```

``-e``は編集可能モードインストールなのですが、「編集可能モード」ってどういうこと？と思って調べたら、下記の記事が大変分かりやすかったです。
https://blog.hgrs.me/20190520094349