Go diliyle test için uygun paket adlandırma


104

Go'da birkaç farklı test paketi adlandırma stratejisi gördüm ve her birinin artılarını ve eksilerini ve hangisini kullanmam gerektiğini öğrenmek istedim.

Strateji 1:

Dosya adı: github.com/user/myfunc.go

package myfunc

Test dosyası adı: github.com/user/myfunc_test.go

package myfunc

Örnek için bzip2'ye bakın .

Strateji 2:

Dosya adı: github.com/user/myfunc.go

package myfunc

Test dosyası adı: github.com/user/myfunc_test.go

package myfunc_test

import (
    "github.com/user/myfunc"
)

Örnek için tele bakınız .

Strateji 3:

Dosya adı: github.com/user/myfunc.go

package myfunc

Test dosyası adı: github.com/user/myfunc_test.go

package myfunc_test

import (
    . "myfunc"
)

Örnek için dizelere bakın .

Go standart kitaplığı strateji 1 ve 2'nin bir karışımını kullanıyor gibi görünüyor. Üçünden hangisini kullanmalıyım? Bu, package *_testpaketlerime özel yöntemleri test edemediğim anlamına geldiğinden, test paketlerime eklenen bir acıdır , ancak belki de farkında olmadığım gizli bir avantajı olabilir mi?


9
Bu soru sadece farklı fikirlerle sonuçlanacak, ama benimkini de ekleyeceğim. Özel yöntemlerinizi test etmenize gerek yoktur. Paketinizin diğer geliştiricilerin kullanacağı arayüzünü test etmek istiyorsunuz. Testler başarısız olursa, özel yöntemlerinizin bir göz atması gerektiğini bilirsiniz.
Brenden

2
Strateji 2 için [tel] ( github.com/btcsuite/btcd/blob/master/wire/msgtx_test.go ) örneği, aslında artık aynı zamanda Strateji 1'in bir örneğidir ...
durp

Yanıtlar:


137

Listelediğiniz üç strateji arasındaki temel fark, test kodunun test edilen kodla aynı pakette olup olmadığıdır. Test dosyasında package myfuncveya kullanma kararı, beyaz kutu veya kara kutu testi package myfunc_testyapmak isteyip istemediğinize bağlıdır .

Bir projede her iki yöntemi de kullanmanın yanlış bir tarafı yoktur. Örneğin, olabilir myfunc_whitebox_test.gove myfunx_blackbox_test.go.

Test Kodu Paket Karşılaştırması

  • Kara Kutu Testi:package myfunc_test Yalnızca dışa aktarılan tanımlayıcıları kullandığınızdan emin olmak için kullanın .
  • Beyaz Kutu Testi:package myfunc Dışa aktarılmayan tanımlayıcılara erişiminiz olması için kullanın . Dışa aktarılmayan değişkenlere, işlevlere ve yöntemlere erişim gerektiren birim testleri için idealdir.

Soruda Listelenen Stratejilerin Karşılaştırması

  • Strateji 1: Dosya myfunc_test.gokullanır package myfunc- Bu durumda içindeki test kodu , bu örnekte olduğu gibi, içinde myfunc_test.gotest edilen kodla aynı pakette olacaktır .myfunc.gomyfunc
  • Strateji 2: Dosya myfunc_test.gokullanır package myfunc_test- Bu durumda, myfunc_test.go"ayrı bir paket olarak derlenecek ve daha sonra ana test ikili programına bağlanacak ve çalıştırılacaktır." [Kaynak: test.go kaynak kodundaki 58-59. Satırlar ]
  • Strateji 3: Dosya nokta notasyonunu myfunc_test.gokullanıyor package myfunc_testancak içe myfuncaktarıyor - Bu, Strateji 2'nin bir çeşididir, ancak içe aktarmak için nokta notasyonunu kullanır myfunc.

1
Strateji 1'in kullanılması, dosyaları _test.gotest edilen paketten ayrı tutacağına da dikkat edilmelidir (Strateji 2 ile aynı davranış). Bu, github.com/golang/go/issues/15315'e
Kevin Deenanauth,

Strateji 3'ün güçlü bir paket kullandığını gördüm, ancak ne anlama geldiğini anlayamıyorum?
PickBoy

1
Bir paketi çatalladım ve değişiklikler yaptım ve şimdi tüm testlerim çatallı paketim yerine orijinal depoyu içe aktarmaya çalışıyor. Strateji 3 ile, "github.com/original/link" i "github.com/my/fork" olarak değiştirmeme gerek yok, çünkü bu sadece referans '.' yerine.
nmarley

1
@KevinDeenanauth Bu beni şaşırttı. Ben sadece bir bulduğumda bir tuzağı bulduğunu düşündü _test.goolmayan bir ile _testbir içeren paket ismi func init()testleri için bazı küresel paket değişkeni değiştirir. Ben hatalıydım.
Zyl

1
@nmarley, .çatal sorununuzu çözmez. Göreli bir ithalat değil. Sadece tanımlayıcıları "mevcut pakete" aktarır.
qaisjp

19

Testlerinizin kapsamına bağlıdır. Paketi dışa aktarılan API aracılığıyla kullandığınızdan emin olmak için muhtemelen yüksek seviyeli testler (entegrasyon, kabul, vb.) Ayrı bir pakete yerleştirilmelidir.

Teste tabi tutulması gereken çok sayıda dahili içeren büyük bir paketiniz varsa, testleriniz için aynı paketi kullanın. Ancak bu, testlerinizin herhangi bir özel duruma erişmesi için bir davetiye değildir. Bu, yeniden düzenlemeyi bir kabusa dönüştürür. Hareket halindeyken yapılar yazdığımda, genellikle arayüzler uyguluyorum. Tek tek tüm yardımcı yöntemlerin / işlevlerin değil, testlerimden çağırdığım arabirim yöntemleridir.


13

Mümkün olduğunda 1. stratejiyi kullanmalısınız. foo_testİçe aktarma döngülerini önlemek için özel paket adını kullanabilirsiniz, ancak bu çoğunlukla oradadır, bu nedenle standart kitaplık aynı mekanizma ile test edilebilir. Örneğin strings, testingpaket bağlı olduğu için strateji 1 ile test edilemez strings. Dediğin gibi, strateji 2 veya 3 ile paketin özel tanımlayıcılarına erişimin yok, bu yüzden mecbur kalmadıkça kullanmamak genellikle daha iyidir.


12
Testlerde özel tanımlayıcılara erişememek nasıl bir erdem değildir?
jub0bs

3
iyi test uygulamalarına göre, bir kod yapısı için dahili uygulama ayrıntılarını test etmezsiniz; yapıyor oğlum, bir kod kokusu
Gerardo Lima

0

Ben yaklaşık eklemek istediğiniz bir önemli notlar import .gelen Golang CodeReviewComments :

import .Formu nedeniyle, testlerde yararlı olabilir dairesel bağımlılıkları test edilen paketin bir parçası yapılamaz:

package foo_test

import (
    "bar/testutil" // also imports "foo"
    . "foo"
)

Bu durumda, test dosyası foo paketini kullandığı için foo paketinde olamaz bar/testutil. Bu yüzden 'ithal' kullanıyoruz. form, dosya olmasa bile foo paketinin bir parçasıymış gibi davranmasını sağlar.

Bu tek durum dışındaimport . , programlarınızda kullanmayın . Quux gibi bir adın mevcut pakette mi yoksa içe aktarılmış bir pakette mi üst düzey bir tanımlayıcı olduğu belirsiz olduğundan programları okumayı çok daha zor hale getirir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.