pytest + seleniumでfixtureを使って共通処理をまとめる

以前の記事でsetup_method/teardown_methodを使って共通処理をまとめました。今回はそれと同様のことをpytestのfixtureというものを使って実現したいと思います。

setup_method/teardown_method を使った方法は以下の記事をご覧ください。

siro-uma.hatenablog.com

環境

手順

前回での記事の内容の通り、setup_method/teardown_methodに記載した処理が共通処理になります。

今回はタイトルにもある通りpytestのFixtureという機能を使っていきます。fixtureとは何か:

pytest fixtures offer dramatic improvements over the classic xUnit style of setup/teardown functions:

https://docs.pytest.org/en/latest/fixture.html#pytest-fixtures-explicit-modular-scalable

pytestの公式ページにある文言を転記させてもらいましたが、今までのxUnitスタイルであるsetup/teardonwを劇的に改善すると書いてあります。

劇的にと言い切るのがすごいですね 笑。それでは実際のコードを見ながらfixtureを紐解いて行きましょう。

conftest.pyという見慣れないファイルがあるの気がつくと思いますが、今回は2つのファイルに分かれています。conftest.pyもpytestの仕組みのひとつになります。conftest.pyはこのpytest fixtureとの相性が良く、今回はこの2つの仕組みを使って、共通処理をまとめていきます。

conftest.py って何?

pytestはpluginを読み込む過程の中で、conftest.pyをtest fileがあるディレクトリ(カレント及び親)から読み込みます。その過程で読み込まれたconftest.pyに記載されている処理は、共通処理として、テストが実行される処理の中で呼び出されます。

https://docs.pytest.org/en/latest/fixture.html#conftest-py-sharing-fixture-functions

fixture って何?

fixtureを使った機能はいくつかあります。その中で今回使うのは2つの機能:

  1. Fixtures as function arguments

@pytest.fixtureアノテーションを関数に付与することで、その関数はfixture objectとして扱われ、Test function (テストケース) の引数として扱うことができます。

今回のサンプルのコードであるconftest.pyの中で、googleという関数を@pytest.fixtureアノテーションが付与されているのがわかると思います。さらに、test_google.pyの中の各テストケースの引数として先程のgoogleという関数を与えています。

更にその引数のgoogleを使ってそれぞれのテストケースでfind_element_by_**を呼んでいます。さて、ここで疑問になるのがgoogleの実体。googleは一体何者なのでしょうか。答えは次に紹介するfixtureの機能にあります。

  1. Fixture finalization / executing teardown code

@pytest.fixtureのついた関数googleの中でもうひとつ見慣れないコードがあります。それはyield

このyieldを使うことで関数内の処理を一旦一時停止して、それ以降の処理を一旦日出し元に返すことができます。pytestのケースでその呼び出し元は実際のテストケースになります(今回の例ではtest_logotest_input_field)。この一時停止の機能により、yieldの前後にsetup_method/teardown_method相当の処理を書くことで、setup_method/teardown_methodと同等の機能を実現することができます。

さらにyieldを使うと、通常のreturnと同様に、呼び出し元に値を返すこともできます。なので、今回は初期化済みのWebdriverであるdriverを返却しています。これにより、呼び出し元であるtest_logoなどのテストでそのままdriverを介した処理を継続することができるのです。

まとめ

今回はpytestのfixtureを使ってテストの前処理と後処理をひとつの実装にまとめてみました。 上述の通りpytestのfixtureは強力で、上記で説明した機能以外にも、fixtureのscopeをfunction以外にもmodulesessionに変更したり、パラメータを渡したりと様々な機能を有しています。興味がある方は以下のリンクから詳細を覗いてみてください。

pytest fixtures: explicit, modular, scalable — pytest documentation