pytestでプライベートメソッドをテストする

毎回ググっているのでここでアウトプットしておきます。

MyClass のプライベートメソッド __bar のテストをしたいとします。

class MyClass:
    def foo(self) -> str:
        return "foo"

    def __bar(self) -> str:
        return "bar"

これをテストしたい場合は以下のようなコードを書きがちですが AttributeError が発生します。

from main import MyClass


class TestMyClass:
    foo = MyClass()

    def test_foo(self) -> None:
        assert self.foo.foo() == "foo"

    def test_bar(self) -> None:
        assert self.foo.__bar() == "bar"  # => E       AttributeError: 'MyClass' object has no attribute '_TestMyClass__bar'

こうすれば解決します。Mypy から attr-defined で怒られてしまうので ignore コメントを入れています。

     def test_bar(self) -> None:
-        assert self.foo.__bar() == "bar"
+        assert self.foo._MyClass__bar() == "bar"  # type: ignore[attr-defined]

「本当にプライベートメソッドのテストが必要か?」「パブリックメソッド経由でテストできるのでは?」という視点は持っておきたいですね。

t-wada.hatenablog.jp