NissyBlog

Life goes on.

テストからファイル単位でfixtureを切り出す方法

この記事は
python Advent Calendar 2017 - Qiita
8日目の記事になります。
こんにちは。@nissy0409240です。

先日、pytesetを用いてユニットテストを書く機会がありました。
その際にfixtureをファイル単位で切り出す方法を教わったので、
忘れないうちに書こうと思います。

言語と環境

Python Advent Calenderですので当然ではありますが
言語はPythonを、
テスティングフレームワークはpytestを使います。

切り出す前

まず、切り出す前のコードを示します。
※実際に行ったコードをそのままコピペするのはちょっとマズいので数分前に強引に書いた例を記載します。

実コード(wordfilter.py)

# -*- coding: utf-8 -*-
import sys


class WordFilter():
    def wordfilter(self, argv, flg):
        if argv.find('hoge') > -1:
            flg = 1
            return argv.replace('hoge', 'XXXX'), flg
        else:
            flg = 0
            return argv, flg

if __name__ == '__main__':
    w = WordFilter()
    flg = None
    ret, flg = w.wordfilter(sys.argv[1, flg])
    print [ret, flg]

テストコード(test_wordfilter.py)

# -*- coding:utf-8 -*-
import unittest
from wordfilter import WordFilter


class TestWordFilter(unittest.TestCase):

    def test_argv_contains_hoge_then_replace_XXXX(self):
        """引数にhogeを含む単語を渡したらhogeがXXXXに置換されて出力される
        """
        print('start')
        input_word = 'hogetest'
        result = WordFilter().wordfilter(input_word, flg=None)
        self.assertEqual(result[0], 'XXXXtest')

    def test_argv_not_contains_hoge_then_not_replace(self):
        """引数にhogeが含む単語を渡したらflgが1になってることを確かめる
        """
        print('start')
        input_word = 'hogetest'
        result = WordFilter().wordfilter(input_word, flg=None)
        self.assertEqual(result[1], True)


if __name__ == '__main__':
    unittest.main()

上記二つのコードのディレクトリ構成は以下の通りとなります。

.
├── __init__.py
├── wordfilter.py
└── test_wordfilter.py

切り出した後

早速、切り出してみます。

実コード(wordfilter.py)

# -*- coding: utf-8 -*-
import sys


class WordFilter():
    def wordfilter(self, argv, flg):
        if argv.find('hoge') > -1:
            flg = 1
            return argv.replace('hoge', 'XXXX'), flg
        else:
            flg = 0
            return argv, flg

if __name__ == '__main__':
    w = WordFilter()
    flg = None
    ret, flg = w.wordfilter(sys.argv[1, flg])
    print [ret, flg]

テストコード(test_wordfilter.py)

# -*- coding:utf-8 -*-
import unittest
import pytest
from wordfilter import WordFilter


@pytest.mark.usefixtures("input_word")
class TestWordFilter(unittest.TestCase):

    def test_argv_contains_hoge_then_replace_XXXX(self):
        """引数にhogeを含む単語を渡したらhogeがXXXXに置換されて出力される
        """
        input_word = 'hogetest'
        result = WordFilter().wordfilter(input_word, flg=None)
        self.assertEqual(result[0], 'XXXXtest')

    def test_argv_not_contains_hoge_then_not_replace(self):
        """引数にhogeが含む単語を渡したらflgが1になってることを確かめる
        """
        input_word = 'hogetest'
        result = WordFilter().wordfilter(input_word, flg=None)
        self.assertEqual(result[1], True)


if __name__ == '__main__':
    unittest.main()

conftest.py

# coding: utf-8

import pytest


@pytest.fixture()
def input_word():
    print('start')

上記三つのコードのディレクトリ構成は以下の通りとなります。

.
├── __init__.py
├── conftest.py
├── test_wordfilter.py
└── wordfilter.py

実際にやったことは以下の二点です

  • 共通部分をconftest.pyに逃す
  • fixtureを適用する

以上となります。
最後までお付き合い頂き、ありがとうございました。