Saya tahu bagaimana saya menggunakan istilah-istilah ini, tetapi saya bertanya-tanya apakah ada definisi yang diterima untuk memalsukan , mengejek , dan mematikan untuk tes unit? Bagaimana Anda mendefinisikan ini untuk tes Anda? Jelaskan situasi di mana Anda dapat menggunakannya masing-masing.
Inilah cara saya menggunakannya:
Palsu : kelas yang mengimplementasikan antarmuka tetapi berisi data tetap dan tidak ada logika. Cukup kembalikan data "baik" atau "buruk" tergantung pada implementasinya.
Mock : kelas yang mengimplementasikan antarmuka dan memungkinkan kemampuan untuk secara dinamis mengatur nilai untuk kembali / pengecualian untuk membuang dari metode tertentu dan menyediakan kemampuan untuk memeriksa apakah metode tertentu telah dipanggil / tidak dipanggil.
Stub : Seperti kelas tiruan, kecuali itu tidak memberikan kemampuan untuk memverifikasi bahwa metode telah dipanggil / tidak dipanggil.
Mengejek dan bertopik dapat dihasilkan atau dihasilkan oleh kerangka kerja mengejek. Kelas palsu dihasilkan dengan tangan. Saya menggunakan tiruan terutama untuk memverifikasi interaksi antara kelas saya dan kelas dependen. Saya menggunakan bertopik setelah saya memverifikasi interaksi dan sedang menguji jalur alternatif melalui kode saya. Saya menggunakan kelas palsu terutama untuk abstrak keluar ketergantungan data atau ketika mengejek / bertopik terlalu membosankan untuk mengatur setiap kali.
sumber
Jawaban:
Anda dapat memperoleh beberapa informasi:
Dari Martin Fowler tentang Mock and Stub
Benda palsu sebenarnya memiliki implementasi yang berfungsi, tetapi biasanya mengambil beberapa jalan pintas yang membuatnya tidak cocok untuk produksi
Rintisan bertopik memberikan jawaban kalengan untuk panggilan yang dilakukan selama tes, biasanya tidak menanggapi apa pun di luar apa yang diprogram dalam tes. Rintisan bertopik juga dapat merekam informasi tentang panggilan, seperti rintisan gateway email yang mengingat pesan yang 'dikirim', atau mungkin hanya berapa banyak pesan yang 'dikirim'.
Mengolok - olok adalah apa yang kita bicarakan di sini: objek diprogram dengan harapan yang membentuk spesifikasi panggilan mereka diharapkan untuk menerima.
Dari xunitpattern :
Palsu : Kami memperoleh atau membangun implementasi yang sangat ringan dengan fungsi yang sama seperti yang disediakan oleh komponen yang menjadi andalan SUT dan memerintahkan SUT untuk menggunakannya alih-alih yang asli.
Stub : Implementasi ini dikonfigurasikan untuk menanggapi panggilan dari SUT dengan nilai (atau pengecualian) yang akan menggunakan Kode yang Belum Diuji (lihat Bug Produksi pada halaman X) dalam SUT. Indikasi kunci untuk menggunakan Test Stub adalah memiliki Kode yang Belum Teruji yang disebabkan oleh ketidakmampuan untuk mengontrol input SUT yang tidak langsung
Objek tiruan yang mengimplementasikan antarmuka yang sama dengan objek tempat SUT (Sistem Diuji) bergantung. Kita dapat menggunakan Objek Mock sebagai titik pengamatan ketika kita perlu melakukan Verifikasi Perilaku untuk menghindari Persyaratan yang Tidak Teruji (lihat Bug Produksi pada halaman X) yang disebabkan oleh ketidakmampuan untuk mengamati efek samping dari metode pemanggilan pada SUT.
Sendiri
Saya mencoba menyederhanakan dengan menggunakan: Mock and Stub. Saya menggunakan Mock ketika itu adalah objek yang mengembalikan nilai yang diatur ke kelas yang diuji. Saya menggunakan rintisan untuk meniru kelas Interface atau Abstrak untuk diuji. Sebenarnya, tidak masalah apa pun sebutan Anda, mereka semua kelas yang tidak digunakan dalam produksi, dan digunakan sebagai kelas utilitas untuk pengujian.
sumber
Stub - sebuah objek yang menyediakan jawaban yang telah ditentukan untuk panggilan metode.
Mock - objek tempat Anda menetapkan harapan.
Palsu - objek dengan kemampuan terbatas (untuk keperluan pengujian), mis. Layanan web palsu.
Test Double adalah istilah umum untuk bertopik, mengolok-olok dan palsu. Tetapi secara informal, Anda akan sering mendengar orang hanya menyebut mereka mengejek.
sumber
EXPECT_CALL()
s pada metode yang diolok-olok yang memaksa keluaran tertentu berdasarkan input tertentu, dengan menggunakan tipe.WillOnce(Invoke(my_func_or_lambda_func))
(atau dengan.WillRepeatedly()
) sintaks terlampir pada sebuahEXPECT_CALL()
. Beberapa contoh penggunaanInvoke()
dapat dilihat dalam konteks berbeda di bagian bawah jawaban panjang saya di sini: stackoverflow.com/a/60905880/4561887 .Invoke()
sini: github.com/google/googletest/blob/master/googlemock/docs/… . Lagi pula, kesimpulannya adalah: Google mock (gmock) memungkinkan seseorang untuk dengan mudah membuat tiruan dan bertopik , meskipun sebagian besar tiruan bukan bertopik.Saya terkejut bahwa pertanyaan ini sudah ada sejak lama dan belum ada yang memberikan jawaban berdasarkan "The Art of Unit Testing" karya Roy Osherove .
Dalam "3.1 Introducing stubs" mendefinisikan sebuah rintisan sebagai:
Dan mendefinisikan perbedaan antara bertopik dan mengolok-olok sebagai:
Palsu hanyalah nama yang digunakan untuk bertopik dan mengolok-olok. Misalnya ketika Anda tidak peduli tentang perbedaan antara bertopik dan mengolok-olok.
Cara Osherove membedakan antara bertopik dan mengolok-olok, berarti bahwa setiap kelas yang digunakan sebagai palsu untuk pengujian dapat berupa sebuah rintisan atau tiruan. Yang mana untuk tes tertentu tergantung sepenuhnya pada bagaimana Anda menulis cek dalam tes Anda.
Contoh tes di mana kelas FakeX digunakan sebagai rintisan:
The
fake
contoh digunakan sebagai sebuah rintisan karenaAssert
tidak menggunakanfake
sama sekali.Contoh tes di mana tes kelas X digunakan sebagai tiruan:
Dalam hal ini
Assert
cek nilai padafake
, membuat tiruan itu palsu.Sekarang, tentu saja contoh-contoh ini sangat dibuat-buat, tetapi saya melihat manfaat besar dalam perbedaan ini. Ini membuat Anda menyadari bagaimana Anda menguji barang-barang Anda dan di mana dependensi tes Anda berada.
Saya setuju dengan Osherove
Menegaskan yang palsu adalah sesuatu yang Anda benar-benar ingin hindari karena membuat tes Anda sangat tergantung pada implementasi kelas yang bukan yang diuji sama sekali. Yang berarti bahwa tes untuk kelas
ActualClassUnderTest
dapat mulai melanggar karena implementasi untukClassUsedAsMock
diubah. Dan itu mengirimkan bau busuk kepada saya. Tes untukActualClassUnderTest
sebaiknya hanya istirahat ketikaActualClassUnderTest
diubah.Saya menyadari bahwa menulis menegaskan bahwa yang palsu adalah praktik yang umum, terutama ketika Anda adalah tipe pelanggan TDD tiruan. Saya kira saya tegas dengan Martin Fowler di kubu klasik (Lihat Martin Fowler "Mocks tidak bertopik" ) dan seperti Osherove menghindari pengujian interaksi (yang hanya dapat dilakukan dengan menyatakan melawan yang palsu) sebanyak mungkin.
Untuk bersenang-senang membaca mengapa Anda harus menghindari ejekan seperti yang didefinisikan di sini, google untuk "fowler mockist classicist". Anda akan menemukan sejumlah besar pendapat.
sumber
Seperti disebutkan oleh jawaban terpilih, Martin Fowler membahas perbedaan-perbedaan ini di Mocks Aron't Stubs , dan khususnya subjudul The Difference Between Mocks and Stubs , jadi pastikan untuk membaca artikel itu.
Daripada berfokus pada bagaimana hal-hal ini berbeda, saya pikir itu lebih mencerahkan untuk fokus pada mengapa ini adalah konsep yang berbeda. Masing-masing ada untuk tujuan yang berbeda.
Palsu
Sebuah palsu adalah sebuah implementasi yang berperilaku "alami", tetapi tidak "nyata". Ini adalah konsep yang kabur dan orang yang berbeda memiliki pemahaman yang berbeda tentang apa yang membuat sesuatu menjadi palsu.
Salah satu contoh palsu adalah basis data dalam memori (misalnya menggunakan sqlite dengan
:memory:
toko). Anda tidak akan pernah menggunakan ini untuk produksi (karena data tidak bertahan), tetapi itu sangat memadai sebagai database untuk digunakan dalam lingkungan pengujian. Ini juga jauh lebih ringan daripada database "nyata".Sebagai contoh lain, mungkin Anda menggunakan beberapa jenis penyimpanan objek (misalnya Amazon S3) dalam produksi, tetapi dalam pengujian Anda bisa menyimpan objek ke file pada disk; maka implementasi "save to disk" Anda akan menjadi palsu. (Atau Anda bahkan bisa memalsukan operasi "simpan ke disk" dengan menggunakan sistem file di memori sebagai gantinya.)
Sebagai contoh ketiga, bayangkan objek yang menyediakan API cache; sebuah objek yang mengimplementasikan antarmuka yang benar tetapi tidak melakukan caching sama sekali tetapi selalu mengembalikan cache miss akan menjadi semacam palsu.
Tujuan dari suatu kepalsuan bukan untuk mempengaruhi perilaku sistem yang diuji , tetapi untuk menyederhanakan implementasi tes (dengan menghapus ketergantungan yang tidak perlu atau kelas berat).
Rintisan bertopik
Sebuah stub merupakan implementasi yang berperilaku "tidak wajar". Ini sudah dikonfigurasikan sebelumnya (biasanya oleh set tes) untuk menanggapi input spesifik dengan output spesifik.
Tujuan dari rintisan adalah untuk menguji sistem Anda ke keadaan tertentu. Misalnya, jika Anda menulis tes untuk beberapa kode yang berinteraksi dengan REST API, Anda bisa mematikan REST API dengan API yang selalu mengembalikan respons kalengan, atau yang menanggapi permintaan API dengan kesalahan tertentu. Dengan cara ini Anda bisa menulis tes yang membuat pernyataan tentang bagaimana sistem bereaksi terhadap keadaan ini; misalnya, menguji respons yang didapat pengguna Anda jika API mengembalikan kesalahan 404.
Sebuah rintisan biasanya diterapkan untuk hanya menanggapi interaksi persis yang Anda katakan untuk ditanggapi. Tetapi fitur kunci yang membuat sesuatu menjadi rintisan adalah tujuannya : rintisan adalah tentang menyiapkan test case Anda.
Mengejek
Sebuah mock mirip dengan rintisan, tapi dengan verifikasi ditambahkan dalam. Tujuan dari mock adalah untuk membuat pernyataan tentang bagaimana sistem Anda di bawah uji berinteraksi dengan ketergantungan .
Misalnya, jika Anda menulis tes untuk sistem yang mengunggah file ke situs web, Anda bisa membuat tiruan yang menerima file dan yang dapat Anda gunakan untuk menyatakan bahwa file yang diunggah benar. Atau, dalam skala yang lebih kecil, adalah hal biasa untuk menggunakan tiruan dari suatu objek untuk memverifikasi bahwa sistem yang diuji memanggil metode tertentu dari objek yang diejek.
Mock terikat pada pengujian interaksi , yang merupakan metodologi pengujian khusus. Orang-orang yang lebih suka menguji keadaan sistem daripada interaksi sistem akan menggunakan ejekan hemat jika sama sekali.
Tes ganda
Palsu, bertopik, dan mengolok-olok semuanya termasuk dalam kategori tes ganda . Tes ganda adalah objek atau sistem apa pun yang Anda gunakan dalam ujian alih-alih yang lain. Sebagian besar pengujian perangkat lunak otomatis melibatkan penggunaan uji ganda atau sejenisnya. Beberapa jenis lain dari ganda tes meliputi nilai-nilai boneka , mata-mata , dan I / O Blackholes .
sumber
Untuk mengilustrasikan penggunaan bertopik dan mengolok-olok, saya ingin juga menyertakan contoh berdasarkan " The Art of Unit Testing " karya Roy Osherove .
Bayangkan, kami memiliki aplikasi LogAnalyzer yang memiliki fungsi tunggal untuk mencetak log. Itu tidak hanya perlu berbicara dengan layanan web, tetapi jika layanan web membuat kesalahan, LogAnalyzer harus mencatat kesalahan ke ketergantungan eksternal yang berbeda, mengirimkannya melalui email ke administrator layanan web.
Inilah logika yang ingin kami uji di dalam LogAnalyzer:
Bagaimana Anda menguji bahwa LogAnalyzer memanggil layanan email dengan benar ketika layanan web mengeluarkan pengecualian? Inilah beberapa pertanyaan yang kami hadapi:
Bagaimana kita bisa mengganti layanan web?
Bagaimana kita bisa mensimulasikan pengecualian dari layanan web sehingga kita dapat menguji panggilan ke layanan email?
Bagaimana kita tahu bahwa layanan email dipanggil dengan benar atau tidak sama sekali?
Kami dapat menangani dua pertanyaan pertama dengan menggunakan rintisan untuk layanan web . Untuk mengatasi masalah ketiga, kita bisa menggunakan objek tiruan untuk layanan email .
Palsu adalah istilah umum yang dapat digunakan untuk menggambarkan stub atau mock. Dalam pengujian kami, kami akan mendapatkan dua pemalsuan. Salah satunya adalah tiruan layanan email, yang akan kami gunakan untuk memverifikasi bahwa parameter yang benar dikirim ke layanan email. Yang lainnya akan menjadi sebuah rintisan yang akan kita gunakan untuk mensimulasikan pengecualian yang dilemparkan dari layanan web. Itu sebuah rintisan karena kami tidak akan menggunakan layanan web palsu untuk memverifikasi hasil tes, hanya untuk memastikan tes berjalan dengan benar. Layanan email adalah tiruan karena kami akan menyatakan bahwa itu disebut dengan benar.
sumber
hal yang Anda tegaskan di atasnya, disebut objek tiruan dan segala sesuatu yang hanya membantu uji coba, adalah sebuah rintisan .
sumber
Ini masalah membuat tes ekspresif. Saya menetapkan harapan pada Mock jika saya ingin tes untuk menggambarkan hubungan antara dua objek. Saya rintisan nilai kembali jika saya menyiapkan objek pendukung untuk membawa saya ke perilaku yang menarik dalam ujian.
sumber
Jika Anda terbiasa dengan Arrange-Act-Assert, maka salah satu cara untuk menjelaskan perbedaan antara rintisan dan tiruan yang mungkin berguna bagi Anda, adalah bahwa rintisan milik bagian pengaturan, karena mereka untuk mengatur keadaan input, dan tiruan milik bagian asert karena mereka untuk menyatakan hasil melawan.
Dummies tidak melakukan apa pun. Mereka hanya untuk mengisi daftar parameter, sehingga Anda tidak mendapatkan kesalahan yang tidak terdefinisi atau nol. Mereka juga ada untuk memuaskan pemeriksa tipe dalam bahasa yang diketik dengan ketat, sehingga Anda dapat diizinkan untuk mengkompilasi dan menjalankan.
sumber
Stub, Fakes, dan Mock memiliki arti berbeda di berbagai sumber. Saya menyarankan Anda untuk memperkenalkan ketentuan internal tim Anda dan menyetujui maknanya.
Saya pikir penting untuk membedakan antara dua pendekatan: - validasi perilaku (menyiratkan penggantian perilaku) - validasi keadaan akhir (menyiratkan emulasi perilaku)
Pertimbangkan pengiriman email jika terjadi kesalahan. Ketika melakukan validasi perilaku - Anda memeriksa bahwa metode
Send
dariIEmailSender
dieksekusi sekali. Dan Anda perlu meniru hasil dari metode ini, mengembalikan ID dari pesan yang dikirim. Jadi Anda berkata: "Saya berharap ituSend
akan dipanggil. Dan saya hanya akan mengembalikan nomor dummy (atau acak) untuk panggilan apa pun" . Ini adalah validasi perilaku:emailSender.Expect(es=>es.Send(anyThing)).Return((subject,body) => "dummyId")
Saat melakukan validasi negara, Anda harus membuat
TestEmailSender
alat ituIEmailSender
. Dan menerapkanSend
metode - dengan menyimpan input ke beberapa struktur data yang akan digunakan untuk verifikasi keadaan di masa depan seperti array dari beberapa objekSentEmails
dan kemudian menguji Anda akan memeriksa yangSentEmails
berisi email yang diharapkan. Ini adalah validasi keadaan:Assert.AreEqual(1, emailSender.SentEmails.Count)
Dari bacaan saya, saya mengerti bahwa validasi Perilaku biasanya disebut Mocks . Dan validasi Negara biasanya disebut Rintisan bertopik atau Palsu .
sumber
stub dan fake adalah objek di mana mereka dapat memvariasikan respons mereka berdasarkan parameter input. perbedaan utama di antara mereka adalah bahwa Palsu lebih dekat dengan implementasi dunia nyata daripada rintisan. Rintisan bertopik pada dasarnya berisi tanggapan kode-keras terhadap permintaan yang diharapkan. Mari kita lihat sebuah contoh:
Sebuah mock adalah langkah dari palsu dan stub. Mock menyediakan fungsi yang sama dengan bertopik tetapi lebih kompleks. Mereka dapat memiliki aturan yang ditentukan untuk mereka yang menentukan bagaimana metode pemesanan pada API mereka harus dipanggil. Kebanyakan pengejek dapat melacak berapa kali suatu metode dipanggil dan dapat bereaksi berdasarkan informasi itu. Mengolok-olok umumnya mengetahui konteks setiap panggilan dan dapat bereaksi secara berbeda dalam situasi yang berbeda. Karena itu, mengejek membutuhkan pengetahuan tentang kelas yang mereka cemooh. sebuah rintisan umumnya tidak dapat melacak berapa kali suatu metode dipanggil atau dalam urutan apa urutan metode dipanggil. Mock terlihat seperti:
sumber
fake object
adalah implementasi nyata dari antarmuka (protokol) atau perluasan menggunakan pewarisan atau pendekatan lain yang dapat digunakan untuk membuat - adalah ketergantungan. Biasanya ini dibuat oleh pengembang sebagai solusi paling sederhana untuk menggantikan beberapa ketergantunganstub object
adalah objek telanjang (0, nihil dan metode tanpa logika) dengan dan ekstra dan telah ditetapkan (oleh pengembang) negara untuk menentukan nilai kembali. Biasanya itu dibuat oleh frameworkmock object
sangat mirip denganstub object
tetapi keadaan tambahan diubah selama eksekusi program untuk memeriksa apakah sesuatu terjadi (metode dipanggil).sumber