2010-05-11 13 views
11

Tôi có một tập lệnh thực hiện nhiều thứ khác nhau và truy cập vào các paramenters bằng sys.argv nhưng khi tập lệnh chuyển đến phần không mã nhất của mã nó nói không có mô-đun cho việc này. Tập lệnh mà tôi có là:Vấn đề với sys.argv [1] khi mô-đun unittest nằm trong tập lệnh

class MyScript(): 

    def __init__(self): 
     self.value = sys.argv[1] 

    def hello(self): 
     print self.value 

    def suite(self): 
     modules_to_test = ('external_sanity_onvif', 'starttest') 
     alltests = unittest.TestSuite() 
     for module in map(__import__, modules_to_test): 
      alltests.addTest(unittest.findTestCases(module)) 
     return alltests 


if __name__ == '__main__': 
    Run = MyScript() 
    Run.hello() 
    log_file = 'log_file.txt' 
    test_file = open(log_file, "w") 
    runner = unittest.TextTestRunner(test_file) 
    unittest.main(defaultTest='Run.suite', testRunner=runner) 

Nói tôi nhập ./script.py Hello vào dòng lệnh. Lỗi tôi nhận được là:

AttributeError: 'module' object has no attribute 'Hello' 

Nếu tôi xóa mô-đun không kích hoạt, nó hoạt động. Ngoài ra, nếu tôi xóa nhật ký thử nghiệm và để nó tại:

unittest.main(defaultTest='Run.suite') 

Điều này vẫn không hoạt động.

Bất kỳ ai cũng có thể trợ giúp.

Cảm ơn

Tôi đã thử bản hack này nhưng vẫn cố đọc sys.argv.

project = sys.argv[4:] 
sys.argv = sys.argv[0:4] 

Tôi đã thử điều này chỉ với argv nhưng vẫn cố gắng đọc các thông số bổ sung.

+1

Bạn có thể đăng thông báo lỗi đầy đủ (với stack trace)? Nó sẽ cho chúng ta biết dòng 'AttributeError' đã xảy ra. – unutbu

Trả lời

16

Vấn đề là unittest.main() muốn quý giá của bạn để sử dụng riêng! Nó sử dụng một trong hai argv bạn cung cấp cho nó như là một tham số chức năng, hoặc sys.argv nếu bạn không cung cấp cho nó argv một cách rõ ràng, và cố gắng để tải các xét nghiệm được đặt tên các đối số bạn cung cấp. Trong trường hợp này, điều này có nghĩa là nó đang tìm kiếm hoặc là một submodule gọi Hello, một lớp TestCase tên Hello, một phương pháp kiểm tra trường hợp trong một lớp test tên Hello, hoặc một đối tượng có thể được gọi tên là Hello mà trả về một TestCase hoặc TestSuite dụ, tất cả trong vòng của bạn module 'script'.

Có một số cách để sửa lỗi này:

  • Bypass unittest.main() và gọi cấp dưới unittest chức năng bản thân để thiết lập và chạy các trường hợp thử nghiệm mà bạn có trong tâm trí.
  • Xóa phụ thuộc của mã của bạn trên sys.argv và sử dụng hành vi unittest.main() cho lợi thế của bạn. Nếu mô-đun của bạn không có nghĩa là chạy độc lập ngoại trừ làm kiểm tra đơn vị, điều này có thể có ý nghĩa, vì người gọi mô-đun của bạn có thể không mong đợi bạn đọc từ argv của họ!
  • Tách mã thử nghiệm và thường trình chính thành một mô-đun thử nghiệm riêng biệt.Bạn vẫn sẽ phải tìm ra cách để có được đúng argv vào mã của bạn mặc dù từ mô-đun thử nghiệm.
  • Chỉ định argv=[sys.argv[0]] làm đối số cho unittest.main(); mà nên giữ nó khỏi cố gắng để đọc của bạn.
-1

Python cung cấp cho bạn tất cả thông tin có thể và trừ khi bạn muốn đăng toàn bộ những thứ bạn đang thử nghiệm, chúng tôi chỉ có thể đoán được những gì bạn đang cố gắng hoàn thành. Lỗi nói rằng không có thuộc tính có tên "Xin chào", vì vậy có thể các mô-đun bạn đang cố gắng kiểm tra sẽ nhận được biến, chức năng hoặc cách khác.

Có lý do nào khiến bạn không chỉ sử dụng unittest.main() không?

+2

Trong pice mã đặc biệt này, tôi đang cố gắng chuyển Hello thành một tham số sẽ hoạt động. Sau đó, tôi có một chức năng gọi một loạt các bài kiểm tra đó là riêng biệt với các chức năng khác. Nhưng khi unittest và sys.argv nằm trong cùng một tập lệnh thì có vấn đề. Các bài kiểm tra tôi đang làm không quan trọng khi chúng hoạt động, vấn đề là khi tôi thử và nhập một tham số vào một hàm không có liên kết unittest và sau đó chạy hàm unittest tiếp tục xuống tệp tôi nhận được lỗi. Lý do tôi sử dụng loại lệnh đơn nhất đó là tôi đang gọi một bộ kiểm thử cụ thể. – chrissygormley

+0

Các thử nghiệm đơn vị của bạn không được lấy tham số từ dòng lệnh. Khung unittest rõ ràng sử dụng sys.argv cho các mục tiêu riêng của nó, mặc dù có thể có cách để ghi đè lên (ví dụ có thể có tham số 'argv' cho các cuộc gọi không liên quan? Tôi không biết tay.) Nếu bạn muốn tham số hóa các bài kiểm tra của bạn, vì vậy bạn có thể tạo nhanh các bộ dữ liệu khác nhau, có lẽ bạn cũng nên làm điều đó thông qua "đồ đạc". Tôi sẽ đăng một câu trả lời khác. –

1

Nói chung, ý tưởng đằng sau thử nghiệm đơn vị là các thử nghiệm chạy mà không có trình điều khiển bên ngoài. Ví dụ. bạn không muốn phụ thuộc vào một số đầu vào từ dòng lệnh. Giải pháp mà bạn đang tìm kiếm có thể là thông qua việc sử dụng Đồ đạc?

import sys 
import unittest 

class MyScript(unittest.TestCase): 
    def setUp(self): 
     self.value = "Default Value" 

    def setHello(self, value): 
     self.value = value 

    def hello(self): 
     return self.value 

class UserA(MyScript): 
    def setUp(self): 
     self.setHello("UserA") 

    def testMyName(self): 
     self.failUnlessEqual(self.hello(), "UserA") 

class UserB(MyScript): 
    def setUp(self): 
     self.setHello("UserB") 

    def testMyName(self): 
     self.failUnlessEqual(self.hello(), "UserB") 

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

Nếu bạn không cần các tính năng dòng lệnh của module unittest, bạn có thể làm cho optparse và các module unittest chơi tốt với nhau bằng cách sửa đổi sys.argv ngay trước khi gọi unittest.main()

Hãy thử này ngay trước cuộc gọi unittest.main() của bạn:

del sys.argv[1:] 

Thao tác này sẽ xóa đối số dòng lệnh của bạn trước khi không nhìn thấy chúng.

Nếu bạn không sử dụng các mô-đun optparse, bạn có thể làm điều này thay vì:

my_args = sys.argv[1:] 
del sys.argv[1:] 
# do_stuff(my_args) 
unittest.main()