Upgrade to Pro — share decks privately, control downloads, hide ads and more …

『テスト駆動Python』入門 ― pytestとテスト駆動開発

『テスト駆動Python』入門 ― pytestとテスト駆動開発

書籍『テスト駆動Python』の内容に沿って、Pythonようテスティングフレームワークであるpytestの簡単な使い方などを紹介します。テスト駆動開発についても触れます。

yattom

June 12, 2019
Tweet

More Decks by yattom

Other Decks in Technology

Transcript

  1. 安井 力 / やっとむ twitter:@yattom https://www.facebook.com/yattom プログラマー Java Python Ruby

    JavaScript テスト駆動開発 アジャイルコーチ ワークショップ 現場導入 技術支援 ゲームを作って一緒に遊ぶ 宝探しアジャイルゲーム、 カンバンゲーム、 心理的安全性ゲーム Python歴 10年以上! (だと思う)
  2. 『テスト駆動Python』とは ― 目次 1. はじめてのpytest 2. テスト関数を作成する 3. pytestのフィクスチャ 4.

    組み込みフィクスチャ 5. プラグイン 6. 構成 7. pytestと他のツールを併用する
  3. 豪華付録も! 付録A. 仮想環境 付録B. pip 付録C. pytestのプラグイン 付録D. Pythonプロジェクトのパッケージ化と配付 付録E.

    xUnitフィクスチャ 付録F. クラウドでpytestを使う 付録G. pytestを用いたテスト駆動開発
  4. 豪華付録も! 付録A. 仮想環境 付録B. pip 付録C. pytestのプラグイン 付録D. Pythonプロジェクトのパッケージ化と配付 付録E.

    xUnitフィクスチャ 付録F. クラウドでpytestを使う 付録G. pytestを用いたテスト駆動開発 pytestに依存しない Pythonの利用方法ガイド 日本語版書き下ろし! 日本語版書き下ろし!
  5. テストの種類について ― まえがきより • ユニットテスト • 統合テスト (インテグレーションテスト、 結合テスト) •

    システムテスト • 機能テスト • 皮下テスト 参考: JSTQBの定義(テストレベル) • コンポーネントテスト • 統合テスト • システムテスト • 受け入れテスト JSTQB=日本ソフトウェアテスト資格認定委員会
  6. 簡単なテストコード user_test.py: from user import User def test_20歳は成人(): sut =

    User(name='yattom', age=20) assert sut.is_adult() def test_10歳は子ども(): sut = User(name='yattomy', age=10) assert sut.is_child()
  7. 簡単なテストコード ― クラスにする user_test.py: class TestUser: def test_20歳は成人(self): sut =

    User(name='yattom', age=20) assert sut.is_adult() def test_10歳は子ども(self): sut = User(name='yattomy', age=10) assert sut.is_child()
  8. pytestは簡単に使える • テストケースの命名 • ファイル名を test_*.py か *_test.py にする •

    関数名の先頭にtestを付ける • クラス名の先頭にTestを付ける • assert • 生のassertで書くだけ • 他ツールではいろいろなassertの書き方を覚えないといけない • 実行結果 • テスト失敗時の表示が懇切丁寧!
  9. フィクスチャの例 @pytest.fixture def clear_db(): pass # データベースを初期化 @pytest.fixture def adult():

    return User(name='yattom', age=20) @pytest.fixture def child(): return User(name='yattomy', age=10) def test_20歳は成人(clear_db, adult): assert adult.is_adult() def test_10歳は子ども(clear_db, child): assert child.is_child()
  10. パラメータテストの例 @pytest.mark.parametrize('age, adult, child', [ (20, True, False), (10, False,

    True), (19, False, True), ]) def test_成人かどうか(age, adult, child): sut = User(name='yattom', age=age) assert sut.is_adult() == adult assert sut.is_child() == child
  11. pytestで使えるモック monkeypatch (組み込みフィクスチャ) • 好きなオブジェクトのアトリビュートやメソッドを自由に置き換える • テストケース内だけで有効、自動で元通りになる • 環境変数も書き換えられる unittest.mock

    (標準ライブラリ) • コード内のテスト対象外のオブジェクトや、組み込みオブジェクトを モック化する • モックへの呼び出しを記録し、正しいか確認する • pytest-mockerプラグインと併用すると便利
  12. monkeypatchの例 def read_file(filename): with open(filename, "r") as f: lines =

    f.readlines() return lines def test_file_read(monkeypatch): import io dummy_stream = io.StringIO("a¥nb¥nc¥n") monkeypatch.setitem(__builtins__, 'open’, lambda a, b: dummy_stream) lines = read_file('dummyfilename’) assert lines == ['a¥n', 'b¥n', 'c¥n']
  13. テスト実行の制御 テストに@pytest.mark.XXXXを付けて、テスト実行を制御できる XXXXに指定する値 • skip • スキップする(実行しない) まだ開発中でテストできない、など • skipif

    • スキップする条件を指定できる • 例: 特定のバージョンの時だけテストする • 自由に指定する • テストに自由にマークを付けて、実行する・しないを指定できる • 例: ローカルの時だけ、CIの時だけ、機能をグループ化する、など
  14. テストの整理分類 • ユニットテスト、コンポーネントテスト • 開発中、手元環境、高速 • 開発者が書く、依存関係や通信などはモックする • 統合テスト •

    人が作ったものと組み合わせる、CI環境 • 開発者やテストエンジニアが書く、モック使いすぎると意味なくなるが必要な場合も • E2E(エンドツーエンド)テスト • フロントエンドや外部通信など引っくるめて、テスト環境 • テストエンジニアが手でやるか自動化、pytest-seleniumの出番(かも) • システムテスト • シナリオベース、時間がかかる、データが必要 • テストエンジニアが手でやる、完全な自動化はまれ
  15. “Pytest - why it‘s more popular than unittest?” なんでPytestはunittestより人気なの? http://www.blog.j-labs.pl/2019/02/Pytest-why-its-more-popular-than-unittest

    • unittestから簡単に乗り換えられた • 複数CPUに分散実行できる • parametrized モジュールを簡単に利用できる • マーク(mark)を使ってテストスイート(テスト群)を整理できる • flake8と統合できる • テスト結果をHTMLで残せる
  16. リファクタリングの対象 • コードをきれいにする • メソッド名、変数名 • インデント • コメント •

    設計も見直す • プロダクトコードもテストコードも見直す • 常にやり続ける • 「動くコード」を保証するテストが前提 大
  17. なぜ「きれい」? • 読みやすさ • シンプル • 予測 • 安全 •

    「動作するもっともシンプルなコード」 • 「もっともシンプル」に到達するには試行錯誤が必要 • きれい、シンプルの基準は、スキルや経験による
  18. 余談: TDDのテストはテストじゃない…? • TDD=開発手法≠テスト手法 • でもテスト書いてるじゃんね • 単純な事実: TDDで書いたテストは 必要なテストすべてを

    網羅しない可能性がある (網羅したかったら 網羅するように 書かないといけない) https://www.slideshare.net/goyoki/votddtdd-tdd-on-live
  19. まとめ • pytestはとっつき易く、修得も早く、痒いところに手が届く • しかも高機能で、さまざまな拡張があり、情報も豊富 • pytestのフィクスチャは最高、知らずに死ぬのはもったいない • プログラマもテストを知るとよいし、 テストエンジニアもpytestを知るとよい

    • テスト駆動開発は楽しいし、開発者にとって強力なツール • リファクタリングは技術的負債の返済 = ハードな先行投資 ≠ 感覚やポリシーの話ではない • テスト駆動開発 = 開発手法 ≠ テスト手法