特定の形式で保存されたファイルと、ファイル内のデータに基づいてオブジェクトを作成するクラスがあります。
オブジェクトの各属性をテストして、ファイル/文字列のすべての値が正しく抽出されたことを確認したいと思います。
これが私がしていることの単純化されたバージョンです:
classlist.py
import re
class ClassList:
def __init__(self, data):
values = re.findall('name=(.*?)\$age=(.*?)\$', data)
self.students = [Student(name, int(age)) for name, age in values]
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
test_classlist.py
import pytest
from classlist import ClassList
def single_data():
text = 'name=alex$age=20$'
return ClassList(text)
def double_data():
text = 'name=taylor$age=23$' \
'name=morgan$age=25$'
return ClassList(text)
@pytest.mark.parametrize('classinfo, expected', [
(single_data(), ['alex']),
(double_data(), ['taylor', 'morgan'])
])
def test_name(classinfo, expected):
result = [student.name for student in classinfo.students]
assert result == expected
@pytest.mark.parametrize('classinfo, expected', [
(single_data(), [20]),
(double_data(), [23, 25])
])
def test_age(classinfo, expected):
result = [student.age for student in classinfo.students]
assert result == expected
さまざまなデータに基づいてオブジェクトを作成し、それらをパラメーター化された値として使用したいと思います。
私の現在のセットアップは機能しますが、テストごとにオブジェクトを作成するという不必要な耳が聞こえます。一度作成してほしいです。
私が次のことをしようとすると:
...
@pytest.fixture(scope='module') # fixture added
def double_data():
text = 'name=taylor$age=23$' \
'name=morgan$age=25$'
return ClassList(text)
@pytest.mark.parametrize('classinfo, expected', [
(single_data, ['alex']),
(double_data, ['taylor', 'morgan']) # () removed
])
def test_name(classinfo, expected):
result = [student.name for student in classinfo.students]
assert result == expected
...
AttributeError: 'function' object has no attribute 'students'
...フィクスチャではなく関数を参照しているため、機能しません。
また、内のコードtest_name
とはtest_age
ほとんど同じです。私の実際のコードでは、約12の属性に対してこれを行っています。これを単一の関数にマージする必要がありますか?どうやって?
テストコードをクリーンアップするにはどうすればよいですか?
ありがとう!
編集:
これは適切だと思いますが、自分の状況でどのように機能するのかわかりません。pytestフィクスチャに渡されたパラメータを変数として渡すことはできますか?
私の現在のセットアップは機能しますが、テストごとにオブジェクトを作成するという不必要な耳が聞こえます。一度作成してほしいです。
これは私には不必要な事前最適化のように聞こえますが、これを気にする場合は、モジュールレベルでテストするデータを作成する関数を実行して、1回だけ実行するようにします。
例えば:
...
def single_data():
text = 'name=alex$age=20$'
return ClassList(text)
def double_data():
text = 'name=taylor$age=23$' \
'name=morgan$age=25$'
return ClassList(text)
double_data_object = double_data()
single_data_object = single_data()
@pytest.mark.parametrize('classinfo, expected', [
(single_data_object, ['alex']),
(double_data_object, ['taylor', 'morgan'])
])
def test_name(classinfo, expected):
result = [student.name for student in classinfo.students]
assert result == expected
@pytest.mark.parametrize('classinfo, expected', [
(single_data_object, [20]),
(double_data_object, [23, 25])
])
def test_age(classinfo, expected):
...
さらに、test_nameとtest_ageのコードはほとんど同じです。私の実際のコードでは、約12の属性に対してこれを行っています。これを単一の関数にマージする必要がありますか?どうやって?
テストコードをクリーンアップするにはどうすればよいですか?
これを行うにはいくつかの方法がありますが、あなたの例から、クラスに等式マジックメソッドを提供し、Student
それを使用してコードをテストします(オブジェクトの正常な表現のreprも追加します)。
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
return (self.name, self.age) == (other.name, other.age)
def __repr__(self):
return 'Student(name={}, age={})'.format(self.name, self.age)
次に、テストは次のようになります。
@pytest.mark.parametrize('classinfo, expected', [
(single_data(), [Student('alex', 20)]),
(double_data(), [Student('taylor', 23), Student('morgan', 25)]),
])
def test_student(classinfo, expected):
assert classinfo.students == expected
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加