Saya telah melihat beberapa strategi penamaan paket pengujian yang berbeda dalam Go dan ingin tahu apa pro dan kontra masing-masing dan mana yang harus saya gunakan.
Strategi 1:
Nama file: github.com/user/myfunc.go
package myfunc
Uji nama file: github.com/user/myfunc_test.go
package myfunc
Lihat bzip2 sebagai contoh.
Strategi 2:
Nama file: github.com/user/myfunc.go
package myfunc
Uji nama file: github.com/user/myfunc_test.go
package myfunc_test
import (
"github.com/user/myfunc"
)
Lihat kabel sebagai contoh.
Strategi 3:
Nama file: github.com/user/myfunc.go
package myfunc
Uji nama file: github.com/user/myfunc_test.go
package myfunc_test
import (
. "myfunc"
)
Lihat string sebagai contoh.
Pustaka standar Go tampaknya menggunakan campuran strategi 1 dan 2. Manakah dari ketiganya yang harus saya gunakan? Ini menyakitkan menambahkan package *_test
paket pengujian saya karena itu berarti saya tidak dapat menguji metode pribadi paket saya tetapi mungkin ada keuntungan tersembunyi yang tidak saya sadari?
sumber
Jawaban:
Perbedaan mendasar antara tiga strategi yang Anda daftarkan adalah apakah kode pengujian berada dalam paket yang sama dengan kode yang diuji. Keputusan untuk menggunakan
package myfunc
ataupackage myfunc_test
dalam file pengujian tergantung pada apakah Anda ingin melakukan pengujian kotak putih atau kotak hitam .Tidak ada salahnya menggunakan kedua metode dalam sebuah proyek. Misalnya, Anda dapat memiliki
myfunc_whitebox_test.go
danmyfunx_blackbox_test.go
.Perbandingan Paket Kode Tes
package myfunc_test
, yang akan memastikan Anda hanya menggunakan pengenal yang diekspor .package myfunc
agar Anda memiliki akses ke pengenal yang tidak diekspor. Baik untuk pengujian unit yang memerlukan akses ke variabel, fungsi, dan metode yang tidak diekspor.Perbandingan Strategi yang Tercantum di Pertanyaan
myfunc_test.go
menggunakanpackage myfunc
- Dalam hal ini kode uji dimyfunc_test.go
akan di paket yang sama seperti kode sedang diuji dimyfunc.go
, yangmyfunc
dalam contoh ini.myfunc_test.go
kegunaanpackage myfunc_test
- Dalam hal ini kode uji dimyfunc_test.go
"akan dikompilasi sebagai paket terpisah, dan kemudian dihubungkan dan menjalankan dengan biner uji utama." [Sumber: Baris 58–59 di kode sumber test.go ]myfunc_test.go
menggunakanpackage myfunc_test
tetapi diimpormyfunc
menggunakan notasi titik - Ini adalah varian dari Strategi 2, tetapi menggunakan notasi titik untuk mengimpormyfunc
.sumber
_test.go
terpisah dari paket yang sedang diuji (perilaku yang sama seperti Strategi 2). Ini tampaknya tidak didokumentasikan per github.com/golang/go/issues/15315_test.go
dengan nama non-_test
paket berisi afunc init()
yang mengubah beberapa variabel paket global untuk pengujian. Saya salah..
tidak menyelesaikan masalah garpu Anda. Ini bukan impor relatif. Itu hanya mengimpor pengidentifikasi "ke dalam paket saat ini".Itu tergantung pada cakupan pengujian Anda. Tes tingkat tinggi (integrasi, penerimaan, dll ...) mungkin harus ditempatkan dalam paket terpisah untuk memastikan bahwa Anda menggunakan paket melalui API yang diekspor.
Jika Anda memiliki paket besar dengan banyak internal yang perlu diuji, gunakan paket yang sama untuk pengujian Anda. Tapi itu bukan undangan bagi pengujian Anda untuk mengakses sedikit pun status privat. Itu akan membuat refactoring menjadi mimpi buruk. Ketika saya menulis struct saat pergi, saya sering mengimplementasikan antarmuka. Ini adalah metode antarmuka yang saya panggil dari pengujian saya, tidak semua metode / fungsi pembantu secara individual.
sumber
Anda harus menggunakan strategi 1 jika memungkinkan. Anda dapat menggunakan
foo_test
nama paket khusus untuk menghindari siklus impor, tetapi sebagian besar ada di sana sehingga pustaka standar dapat diuji dengan mekanisme yang sama. Misalnya,strings
tidak dapat diuji dengan strategi 1 karenatesting
paketnya bergantungstrings
. Seperti yang Anda katakan, dengan strategi 2 atau 3 Anda tidak memiliki akses ke pengenal pribadi paket, jadi biasanya lebih baik untuk tidak menggunakannya kecuali Anda harus melakukannya.sumber
Satu catatan penting yang ingin saya tambahkan
import .
dari Golang CodeReviewComments :The
import .
Bentuk dapat berguna dalam tes itu, karena melingkar dependensi, tidak dapat dibuat bagian dari paket yang diuji:Dalam kasus ini, file pengujian tidak dapat berada dalam paket foo karena digunakan
bar/testutil
, yang mengimpor foo. Jadi kami menggunakan 'impor.' formulir untuk membiarkan file berpura-pura menjadi bagian dari paket foo meskipun sebenarnya bukan.Kecuali untuk kasus yang satu ini, jangan gunakan
import .
dalam program Anda. Itu membuat program lebih sulit dibaca karena tidak jelas apakah nama seperti Quux adalah pengenal tingkat atas dalam paket saat ini atau dalam paket yang diimpor.sumber