2014-05-16 15 views
9

Vay. Bu gece, unittest modülünü kullanarak yazılan Python birim testlerinin trace modülü kapsamındaki kapsama analizi ile iyi oynamadıklarını öğrendim. İşte foobar.py yılında, mümkün olan en basit birim test var:unittest.py trace.py ile iyi uyum sağlamıyor - neden?

. 
---------------------------------------------------------------------- 
Ran 1 test in 0.000s 

OK 

Yüksek,:

import unittest 

class Tester(unittest.TestCase): 
    def test_true(self): 
     self.assertTrue(True) 

if __name__ == "__main__": 
    unittest.main() 

Ben python foobar.py ile bu çalıştırırsanız, bu çıktıyı almak. Şimdi de kapsama testi gerçekleştirmek için istiyorum, bu yüzden python -m trace --count -C . foobar.py ile yeniden çalıştırın, ama şimdi bu olsun:

---------------------------------------------------------------------- 
Ran 0 tests in 0.000s 

OK 

Hayır, Python, sorun değil - sen benim testi vermedi! trace bağlamında çalışan bir şekilde unittest 's test algılama mekanizmasını gums gibi görünüyor.

import unittest 

class Tester(unittest.TestCase): 
    def test_true(self): 
     self.assertTrue(True) 

class Insane(object): 
    pass 

if __name__ == "__main__": 
    module = Insane() 
    for k, v in locals().items(): 
     setattr(module, k, v) 

    unittest.main(module) 

Bu temelde bunun bir kopyasını taklit yoluyla üst düzey modülünün soyut Birileri adını şeyleştirmesi bir geçici çözüm: İşte ben ile geldi (deli) çözüm. Daha sonra bu adı trace'un üzerinde bulunan herhangi bir etkiyi yapmak için unittest.main() numarasına geçebilirim. Size çıktıyı göstermeye gerek yok; Yukarıdaki başarılı örnek gibi görünüyor.

  1. Burada neler oluyor:

    Yani, iki sorum var? trace neden unittest için şeyleri topluyor?

  2. Bu sorunu çözmek için daha kolay ve/veya daha az deli bir yol var mı?

cevap

7

Daha basit bir çözüm unittest.main için açıkça modülün ismini geçmektir:

import unittest 

class Tester(unittest.TestCase): 
    def test_true(self): 
     self.assertTrue(True) 

if __name__ == "__main__": 
    unittest.main(module='foobar') 
trace, modülün nasıl yüklendiğinden dolayı unittest numaralı telefondan çalışıyor. trace, modül kaynak kodunu okur, derler ve __name__ global '__main__''a ayarlı bir bağlamda yürütür. Bu, çoğu modülün ana modül olarak adlandırılmış gibi davranmasını sağlamak için yeterlidir, ancak Python yorumlayıcısında __main__ olarak kayıtlı olan modülü değiştirmez. unittest, __main__ modülünün test durumlarını taramasını istediğinde, aslında birim sınamalarını içermeyen komut satırından çağrılan trace modülünü alır.

coverage.pycoverage.py, sys.modules numaralı belgede hangi modülün __main__ olarak adlandırıldığını değiştirmenin farklı bir yaklaşımını kullanır.

+0

Harika bir açıklama, teşekkürler. Test modülüne kendi (dosya) isminin ne olduğunu ve hem kendi başına hem de trace.py altında bir çekicilik gibi çalıştığını söylemem gerek. –

+0

btw: 'unittest.main (= 'testleri' modülü)': ​​'piton -m Cprofile [some_test_file.py] 'aynı sorun, aynı çözelti sahip olan Cprofile ve unittest kullanmak için çalışıyorum. Arama motorları Cprofile özgü bir şey bulamadık, bu yüzden yorum ekleyerek arama yardım etmeye. –

3

düzgün çalışmıyor neden trace bilmiyorum ama coverage.py yapar:

$ coverage run foobar.py 
. 
---------------------------------------------------------------------- 
Ran 1 test in 0.001s 

OK 
$ coverage report 
Name  Stmts Miss Cover 
---------------------------- 
foobar  6  0 100% 
+0

Ben cover.py'yi seviyorum, ancak trace.py'ye geçtim çünkü ürettiği * .cover dosyalarına ihtiyacım vardı (CDash tarafından yürütülen otomatik kapsama analizi için). Bu dosyaları yayımlamak için, yayınlanmış bir paket var mı? –

+0

Bir .cover dosyasında ne olduğunu bilmiyorum, ancak bunları datacover.py toplamasından yapmak o kadar da zor olamazdı. E-posta üzerinden iletişime geçebilmemiz için bu konu hakkında konuşabiliriz. –

İlgili konular