Saat ini saya memiliki beberapa unit test yang berbagi serangkaian tes umum. Ini sebuah contoh:
import unittest
class BaseTest(unittest.TestCase):
def testCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTest):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTest):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
if __name__ == '__main__':
unittest.main()
Output di atas adalah:
Calling BaseTest:testCommon
.Calling BaseTest:testCommon
.Calling SubTest1:testSub1
.Calling BaseTest:testCommon
.Calling SubTest2:testSub2
.
----------------------------------------------------------------------
Ran 5 tests in 0.000s
OK
Apakah ada cara untuk menulis ulang di atas sehingga yang pertama testCommon
tidak dipanggil?
EDIT: Alih-alih menjalankan 5 tes di atas, saya ingin hanya menjalankan 4 tes, 2 dari SubTest1 dan 2 dari SubTest2. Tampaknya Python unittest menjalankan BaseTest sendiri dan saya perlu mekanisme untuk mencegah hal itu terjadi.
python
unit-testing
testing
Thierry Lam
sumber
sumber
Jawaban:
Gunakan multiple inheritance, jadi kelas Anda dengan tes umum tidak dengan sendirinya mewarisi dari TestCase.
sumber
setUp
dantearDown
metode keCommonTests
kelas, dan Anda ingin mereka dipanggil untuk setiap tes di kelas turunan, Anda harus membalik urutan kelas dasar, sehingga akan:class SubTest1(CommonTests, unittest.TestCase)
.unittest.TestCase
danCommonTests
. Saya pikirsetUpClass
metode di bawah ini adalah yang terbaik dan kurang rentan terhadap kesalahan manusia. Entah itu atau membungkus kelas BaseTest dalam kelas wadah yang sedikit lebih hacky tetapi menghindari pesan lewati dalam cetakan uji coba.CommonTests
memanggil metode yang tidak ada di kelas itu.Jangan gunakan banyak pewarisan, itu akan menggigit Anda nanti .
Sebagai gantinya, Anda bisa memindahkan kelas dasar ke modul terpisah atau membungkusnya dengan kelas kosong:
Hasil:
sumber
Anda dapat memecahkan masalah ini dengan satu perintah:
Jadi kodenya akan terlihat seperti ini:
sumber
self.assert*
metode tidak ada dalam objek standar.super( BaseTest, cls ).setUpClass( )
BaseTest
dapat dirujuk melaluisuper(self.__class__, self)
atau hanyasuper()
dalam subkelas, meskipun tampaknya tidak jika Anda mewarisi konstruktor . Mungkin ada juga alternatif "anonim" ketika kelas dasar perlu referensi itu sendiri (bukan karena saya punya ide ketika kelas perlu referensi sendiri).Jawaban Matthew Marshall bagus, tetapi mengharuskan Anda mewarisi dari dua kelas di setiap kasus uji Anda, yang rawan kesalahan. Sebagai gantinya, saya menggunakan ini (python> = 2.7):
sumber
Apa yang ingin Anda capai? Jika Anda memiliki kode tes umum (pernyataan, tes templat, dll), kemudian tempatkan dalam metode yang tidak diawali dengan
test
jadiunittest
tidak akan memuatnya.sumber
Jawaban Matthew adalah yang perlu saya gunakan karena saya masih di 2,5. Tetapi mulai 2.7 Anda dapat menggunakan dekorator @ unittest.skip () pada metode pengujian apa pun yang ingin Anda lewati.
http://docs.python.org/library/unittest.html#skipping-tests-and-expected-failures
Anda harus menerapkan dekorator lompatan Anda sendiri untuk memeriksa jenis dasar. Belum pernah menggunakan fitur ini sebelumnya, tetapi dari atas kepala saya, Anda dapat menggunakan BaseTest sebagai jenis penanda untuk mengkondisikan lompatan:
sumber
Salah satu cara yang saya pikirkan untuk menyelesaikan ini adalah dengan menyembunyikan metode tes jika kelas dasar digunakan. Dengan cara ini tes tidak dilewati, sehingga hasil tes bisa menjadi hijau, bukan kuning di banyak alat pelaporan pengujian.
Dibandingkan dengan metode mixin, ide seperti PyCharm tidak akan mengeluh bahwa metode unit test hilang dari kelas dasar.
Jika kelas dasar mewarisi dari kelas ini, itu perlu mengganti metode
setUpClass
dantearDownClass
.sumber
Anda bisa menambahkan
__test_ = False
di kelas BaseTest, tetapi jika Anda menambahkannya, ketahuilah bahwa Anda harus menambahkan__test__ = True
di kelas turunan untuk dapat menjalankan tes.sumber
Pilihan lain adalah tidak mengeksekusi
Alih-alih itu bisa Anda gunakan
Jadi, Anda hanya menjalankan tes di kelas
TestClass
sumber
unittest.main()
dikumpulkan ke dalam suite default Anda membentuk suite eksplisit dan menjalankan tesnya.Saya membuat hal yang sama dari @Vladim P. ( https://stackoverflow.com/a/25695512/2451329 ) tetapi sedikit dimodifikasi:
dan di sana kita pergi.
sumber
Pada Python 3.2, Anda bisa menambahkan fungsi test_loader ke modul untuk mengontrol tes mana (jika ada) yang ditemukan oleh mekanisme penemuan tes.
Misalnya, berikut ini hanya akan memuat poster asli
SubTest1
danSubTest2
Kasus Uji, mengabaikanBase
:Ini seharusnya mungkin untuk iterate atas
standard_tests
(aTestSuite
yang berisi tes loader bawaan ditemukan) dan copy semua tapiBase
untuksuite
sebaliknya, tetapi sifat bersarangTestSuite.__iter__
merek yang lebih banyak rumit.sumber
Ubah nama metode testCommon menjadi sesuatu yang lain. Unittest (biasanya) melewatkan apa pun yang tidak memiliki 'tes' di dalamnya.
Cepat dan sederhana
sumber
Jadi ini semacam utas lama tapi saya menemukan masalah ini hari ini dan memikirkan hack saya sendiri untuk itu. Ia menggunakan dekorator yang membuat nilai-nilai fungsi Tidak ada ketika diakses melalui kelas dasar. Tidak perlu khawatir tentang pengaturan dan pengaturan kelas karena jika baseclass tidak memiliki tes mereka tidak akan berjalan.
sumber
Berikut adalah solusi yang hanya menggunakan fitur unittest yang terdokumentasi dan yang menghindari status "lewati" dalam hasil pengujian Anda:
Cara kerjanya: sesuai
unittest.TestCase
dokumentasi , "Setiap instance TestCase akan menjalankan metode basis tunggal: metode ini bernama methodName." "RunTests" default menjalankan semua metode tes * di kelas — begitulah cara kerja TestCase biasanya. Tetapi ketika menjalankan dalam kelas dasar abstrak itu sendiri, Anda bisa menimpa perilaku itu dengan metode yang tidak melakukan apa-apa.Efek sampingnya adalah jumlah tes Anda akan bertambah satu: "tes" runNoTestsInBaseClass akan dihitung sebagai tes yang berhasil ketika dijalankan pada BaseClass.
(Ini juga bekerja dengan Python 2.7, jika Anda masih pada itu. Hanya perubahan
super()
kesuper(BaseTest, self)
.)sumber
Ubah nama metode BaseTest untuk mengatur:
Keluaran:
Dari dokumentasi :
sumber
setUp
?test...
metode,setUp
dieksekusi berulang-ulang, sekali per metode tersebut; jadi BUKAN itu ide yang bagus!