2012-09-19 14 views
20

Tôi muốn mô-đun không khai thác Python của tôi để báo cho người thử nghiệm bỏ qua toàn bộ trong một số trường hợp (chẳng hạn như không thể nhập mô-đun hoặc tìm tài nguyên quan trọng).Làm cách nào để bỏ qua toàn bộ mô-đun unittest của Python tại thời gian chạy?

Tôi có thể sử dụng @unittest.skipIf(...) để bỏ qua lớp Unittest.TestCase, nhưng làm cách nào để bỏ qua toàn bộ mô-đun? Áp dụng bỏ qua cho mọi lớp là không đủ vì bản thân các định nghĩa lớp có thể gây ra ngoại lệ nếu mô-đun không nhập được.

+2

FYI, có một bài đăng trên blog về chính xác điều này tại http://colinnewell.wordpress.com/2012/08/31/skippng-python-unit-tests-if-a-dependency-is-missing/ –

+1

@Mu Mind, điều này có tác dụng ngoại trừ việc tôi đang nói "mũi" thành "thất bại nhanh". Gọi 'unittest.SkipTest()' dường như được tính là lỗi và tạm dừng thực thi. –

Trả lời

6

Sau khi xem xét các answe khác rs ở đây, đây là câu trả lời tốt nhất mà tôi đã đưa ra. Nó xấu xí, nhúng toàn bộ bộ thử nghiệm trong xử lý ngoại lệ, nhưng nó dường như làm những gì bạn muốn. Cụ thể bỏ qua các kiểm tra khi nhập khẩu không hoạt động.

Giả sử bạn đang nói về việc sử dụng nosetests -x để chạy các kiểm tra cần thực hiện trong quá khứ các thử nghiệm bỏ qua, ít nhất nó xuất hiện khi tôi thử nó.

import unittest 
try: 
    import PyQt4 
    # the rest of the imports 


    # actual tests go here. 
    class TestDataEntryMixin(unittest.TestCase): 
     def test_somefeature(self): 
      # .... 

except ImportError, e: 
    if e.message.find('PyQt4') >= 0: 
     class TestMissingDependency(unittest.TestCase): 

      @unittest.skip('Missing dependency - ' + e.message) 
      def test_fail(): 
       pass 
    else: 
     raise 

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

Nếu quá trình nhập không thành công, nó sẽ thay thế chạy thử bằng một lần kiểm tra đơn giản bỏ qua. Tôi cũng đã cố gắng để đảm bảo rằng nó không nuốt bất kỳ trường hợp ngoại lệ vô ý. Giải pháp này nợ rất nhiều cho tất cả các câu trả lời và nhận xét khác cho câu hỏi.

Nếu bạn chạy nó trong chế độ verbose bạn sẽ thấy điều này khi nó bỏ qua,

test_fail (test_openihm_gui_interface_mixins.TestMissingDependency) ... skipped 'Missing dependency - No module named PyQt4' 
+0

Tôi nghĩ đây là câu trả lời hay nhất, nhưng bạn nói đúng, nó xấu xí. :-) –

+0

Nhận 'Ngừng sử dụngCảnh báo: BaseException.message đã không được chấp nhận như của Python 2.6'? Bạn cần thực hiện việc này: http://stackoverflow.com/questions/1272138/baseexception-message-deprecated-in-python-2-6 – crazysim

2

Nó có thể là bẩn để đặt tất cả các định nghĩa lớp con unittest.TestCase trong một khối try...except nhưng nó sẽ làm việc:

import unittest 
try: 
    import eggs 
    class Spam(unittest.TestCase): 
     pass 
    class Ham(unittest.TestCase): 
     pass 
    # ... 
except ImportError: 
    # print 'could not import eggs' 
    pass 

Không ai trong số các tiểu lớp sẽ được xác định nếu việc nhập khẩu eggs thất bại và tất cả những các lớp học() bị bỏ qua. Sẽ không được phản ánh trong đầu ra (tốt hay xấu tùy thuộc vào những gì bạn muốn).

+0

Một giải pháp dơ bẩn đối với một vấn đề khó khăn không quá tệ;) –

+1

@Mu Mind, nó có thực sự bị lôi cuốn không? Trường hợp sử dụng của tôi đang chạy bộ thử nghiệm trên nhiều nền tảng (một số trong số đó có thể không có khả năng 'nhập trứng'). –

+0

Tôi chủ yếu là cho bạn một thời gian khó khăn. Tôi nghĩ rằng một chút về các định nghĩa lớp không nghe có vẻ hơi lạ, nhưng việc vô hiệu hóa "mô-đun này" có vẻ sạch hơn là vô hiệu hóa "tất cả các lớp trong mô-đun này". –

12

Nếu bạn xem định nghĩa unittest.skipIfunittest.skip, bạn có thể thấy rằng phím đang thực hiện raise unittest.SkipTest(reason) khi thử nghiệm được thực hiện. Nếu bạn đang okay với việc có nó hiển thị như một bỏ qua bài kiểm tra thay vì một vài trong testrunner, bạn chỉ có thể nâng unittest.SkipTest mình về nhập khẩu:

import unittest 
try: 
    # do thing 
except SomeException: 
    raise unittest.SkipTest("Such-and-such failed. Skipping all tests in foo.py") 

Chạy với nosetests -v cho:

Failure: SkipTest (Such-and-such failed. Skipping all tests in foo.py) ... SKIP: 
Such-and-such failed. Skipping all tests in foo.py 

---------------------------------------------------------------------- 
Ran 1 test in 0.002s 

OK (SKIP=1) 
+0

Tôi không biết nếu điều đó sẽ làm việc tại * module * phạm vi; 'loader.py' dường như gợi ý rằng module bị lỗi nếu nó ném * bất kỳ * ngoại lệ nào. – nneonneo

+0

Tôi đã thử nó chạy thử nghiệm với nosetests và nó làm việc tốt. Chỉnh sửa câu trả lời của tôi để thêm đầu ra thực tế ... –

+2

'nosetests'! =' Unittest', mặc dù chúng sử dụng cùng một thư viện. Khá chắc chắn nó không cho đồng bằng 'unittest'. – nneonneo

2

Cố gắng xác định một chức năng tùy chỉnh load_tests trong module của bạn:

import unittest 
try: 
    (testcases) 
except ImportError as e: 
    def load_tests(*args, **kwargs): 
     print("Failed to load tests: skipping") 
     return unittest.TestSuite() # no tests 
+1

Tôi thích cách tiếp cận này. Nó có lẽ sẽ tốt hơn nếu nó thực hiện một số loại sử dụng cơ chế SkipTest thay vì chỉ là một 'print' vì đầu ra đó có thể bị chết đuối trong một loạt các kết quả/kết quả thử nghiệm khác. –

+0

Có thể. Chỉ cần có 'TestSuite' chứa một trường hợp kiểm tra giả cho biết nó đã bị bỏ qua. (Trình tải 'loader' của mô-đun 'unittest' thực hiện một điều tương tự, tạo ra các trường hợp kiểm tra lỗi được bảo đảm nếu ví dụ: việc nhập không thành công). – nneonneo

6

tôi thấy rằng việc sử dụng skipTest trong thiết lập làm việc tốt. Nếu bạn cần một mô-đun được nhập, bạn sử dụng khối thử để đặt, ví dụ: module_failed = True, và trong setUp call skipTest nếu nó được thiết lập. Này báo cáo con số chính xác số lần bỏ qua kiểm tra chỉ với một khối try ngắn cần thiết:

import unittest 

try: 
    import my_module 
    module_failed = False 
except ImportError: 
    module_failed = True 

class MyTests(unittest.TestCase): 
    def setUp(self): 
     if module_failed: 
      self.skipTest('module not tested') 

    def test_something(self): 
      #... 
3

Các solution đề xuất bởi các công trình otus và dễ dàng hơn so với các giải pháp chấp nhận theo ý kiến ​​của tôi. Nhưng có ít nhất một nhược điểm.Nếu bạn truy vấn my_module trong một trang trí để bỏ qua một bài kiểm tra duy nhất như

@unittest.skipIf(my_module.support_foo, 'foo not supported') 
def test_foo(self): 
... 

bạn sẽ nhận được một NameError: name 'my_module' is not defined. Các giải pháp được đưa bỏ bên định nghĩa hàm:

def test_foo(self): 
    if not my_module.support_foo: 
     self.skipTest('foo not supported') 
0

Kết hợp các câu trả lời được đề cập và sử dụng this answer:

import unittest 
def module_exists(module_name): 
    try: 
     __import__(module_name) 
    except ImportError: 
     return False 
    else: 
     return True 

class TestClass(unittest.TestCase): 

    @unittest.skipUnless(module_exists("moduleA"), 'ModuleA not installed') 
    def test_something(self): 
     # test something with moduleA 
1

Đối với python 2.7+ (hoặc sử dụng backport unittest2):

... 

import unittest 

def setUpModule(): 
    try: 
     import something 
    except ImportError as err: 
     raise unittest.SkipTest(str(err)) 

class Tests(unittest.TestCase): 
    @classmethod 
    def setUpClass(cls): 
     try: 
      import something 
     except ImportError as err: 
      raise unittest.SkipTest(str(err)) 
... 
Các vấn đề liên quan