Menguji kasus uji unit tunggal dengan banyak perlengkapan/skenario di Pytest

Saya memiliki kelas yang mewakili keadaan kompleks tertentu. Keadaan itu dapat berubah, dan saya mempunyai contoh lain dari kelas itu yang mewakili keadaan "sebenarnya". Saya menulis sebuah fungsi yang melakukan beberapa logika berbeda dan mencari cara untuk mendapatkan keadaan saat ini ke keadaan sebenarnya, jika berbeda.

Saya ingin menguji fungsi itu menggunakan pytest. Ada banyak kemungkinan skenario, tetapi logika pengujiannya cukup sederhana dan bermuara pada (kode python semu):

def test_diffing(current_state, prescribed_state):
    properties_to_add = []
    properties_to_delete = []
    properties_to_modify = []
    properties_to_add, properties_to_delete, properties_to_modify = diff_logic(current_state, prescribed_state)

    assert properties_to_add == 1
    assert properties_to_delete == 0
    assert properties_to_modify == 3

Angka-angka di sisi kanan pernyataan bergantung pada current_state itu. Saya punya banyak current_state skenario.

Apa cara terbaik untuk menulis pengujian unit tunggal seperti di atas, dengan banyak pasang perlengkapan sehingga kondisi_saat ini diteruskan bersama dengan nilai yang diharapkan dari pernyataan tersebut?

Saya telah melihat parameterisasi perlengkapan pytest tetapi masalah dengan pendekatan ini adalah pendekatan ini menggunakan dekorator dan menjadi jelek* dengan sangat cepat, terutama dengan sejumlah besar argumen dan sejumlah besar kasus uji. Tampaknya bukan ini yang seharusnya saya gunakan untuk perlengkapan.

Apa cara terbaik untuk mencapai apa yang saya coba lakukan dengan bersih?

*Menurut saya ini menjadi jelek karena memiliki 15 atau 20 rangkaian argumen kepada seorang dekorator sangat membingungkan dan menempatkan banyak logika pada dekorator itu sendiri.


person darksky    schedule 11.07.2017    source sumber
comment
Jika pemahaman saya benar, perlengkapan lebih untuk kesamaan antar tes, bukan untuk memvariasikan masukan. Dalam kasus Anda, Anda mungkin lebih baik menulis 15-20 pengujian unit jika Anda menguji 15-20 skenario unik.   -  person Avantol13    schedule 11.07.2017
comment
Itu masuk akal. Apa cara terbaik untuk menghindari duplikasi logika yang sama persis sebanyak 15-20 kali? Satu-satunya perbedaan adalah objek current_state beserta ekspektasinya.   -  person darksky    schedule 11.07.2017


Jawaban (1)


Saya pikir Anda dapat menggunakan perlengkapan berparametri untuk mendapatkan apa yang Anda inginkan ingin.

Bagaimana dengan sesuatu seperti:

@pytest.fixture(params=[
    {
        'current_state': 'foo',
        'expected': {
            'properties_to_add': 1,
            'properties_to_delete': 2,
            'properties_to_modify': 3,
        },
    },
    ... as many scenarios as you'd like ...
])
def bundle(request):
    return request.param

@pytest.fixture
def current_state(bundle):
    return bundle['current_state']

@pytest.fixture
def expected(bundle):
    return bundle['expected']

Saya menggunakan konstruksi perlengkapan "bundel" untuk menyatukan input dan output. Kemudian tesnya terlihat sangat bersih:

def test_diffing(current_state, expected):
    prescribed_state = ...  # I assume this is a constant, you can inject "prescribed_state" in the fixture in the same way as "current_state" and "expected"
    properties_to_add, properties_to_delete, properties_to_modify = diff_logic(current_state, prescribed_state)
    assert expected == {
        'properties_to_add': properties_to_add,
        'properties_to_delete': properties_to_delete,
        'properties_to_modify': properties_to_modify,
    }

Kemudian jika struktur data "params" (untuk perlengkapan "bundel") menjadi sangat besar, Anda dapat mendefinisikannya di tempat lain dan memformat kode agar mudah dibaca, memuatnya dari file data, dll.

person Frank T    schedule 11.07.2017