UnitTest Framework - Hướng dẫn nhanh

Kiểm thử đơn vị là một phương pháp kiểm thử phần mềm trong đó các đơn vị mã nguồn riêng lẻ, chẳng hạn như các chức năng, phương pháp và lớp được kiểm tra để xác định xem chúng có phù hợp để sử dụng hay không. Một cách trực quan, người ta có thể xem một đơn vị là phần nhỏ nhất có thể kiểm tra được của một ứng dụng. Các bài kiểm tra đơn vị là các đoạn mã ngắn được lập trình viên tạo ra trong quá trình phát triển. Nó tạo cơ sở cho việc kiểm tra thành phần.

Kiểm thử đơn vị có thể được thực hiện theo hai cách sau:

Kiểm tra bằng tay Kiểm tra tự động

Việc thực thi các trường hợp kiểm thử theo cách thủ công mà không có bất kỳ công cụ hỗ trợ nào được gọi là kiểm thử thủ công.

  • Vì các trường hợp kiểm thử được thực thi bởi nguồn nhân lực nên nó rất time consuming and tedious.

  • Vì các trường hợp kiểm thử cần được thực thi theo cách thủ công nên cần có nhiều người kiểm tra hơn trong kiểm thử thủ công.

  • Nó kém tin cậy hơn vì các thử nghiệm có thể không được thực hiện với độ chính xác mỗi lần do lỗi của con người.

  • Không có lập trình nào có thể được thực hiện để viết các bài kiểm tra phức tạp lấy thông tin ẩn.

Nhận công cụ hỗ trợ và thực hiện các trường hợp kiểm thử bằng cách sử dụng công cụ tự động hóa được gọi là kiểm thử tự động hóa.

  • Fast Automation chạy các trường hợp kiểm thử nhanh hơn đáng kể so với nguồn nhân lực.

  • Các investment over human resources is less như các trường hợp thử nghiệm được thực thi bằng cách sử dụng công cụ tự động hóa.

  • Kiểm tra tự động hóa thực hiện chính xác cùng một hoạt động mỗi khi chúng được chạy và are more reliable.

  • Người kiểm tra can program sophisticated tests để đưa ra thông tin ẩn.

JUnit là một khung kiểm thử đơn vị cho ngôn ngữ lập trình Java. JUnit đóng vai trò quan trọng trong quá trình phát triển theo hướng thử nghiệm và là một trong số họ các khuôn khổ kiểm thử đơn vị được gọi chung là xUnit có nguồn gốc từ JUnit. Bạn có thể tìm hiểu Hướng dẫn sử dụng JUnit tại đây.

Khung kiểm tra đơn vị Python, đôi khi được gọi là “PyUnit”, là một phiên bản ngôn ngữ Python của JUnit được phát triển bởi Kent Beck và Erich Gamma. PyUnit tạo thành một phần của Thư viện chuẩn Python kể từ phiên bản Python 2.1.

Khung thử nghiệm đơn vị Python hỗ trợ tự động hóa thử nghiệm, chia sẻ mã thiết lập và tắt cho các thử nghiệm, tổng hợp các thử nghiệm thành bộ sưu tập và tính độc lập của các thử nghiệm với khung báo cáo. Mô-đun đơn nhất cung cấp các lớp giúp dễ dàng hỗ trợ những phẩm chất này cho một tập hợp các bài kiểm tra.

Hướng dẫn này đã được chuẩn bị cho người mới bắt đầu để giúp họ hiểu chức năng cơ bản của khung kiểm thử Python. Sau khi hoàn thành hướng dẫn này, bạn sẽ thấy mình ở mức độ chuyên môn vừa phải trong việc sử dụng khung thử nghiệm Python, từ đó bạn có thể đưa mình lên các cấp độ tiếp theo.

Bạn nên có chuyên môn hợp lý về phát triển phần mềm bằng ngôn ngữ Python. Hướng dẫn Python của chúng tôi là một nơi tốt để bắt đầu học Python. Kiến thức cơ bản về kiểm thử phần mềm cũng là mong muốn.

Thiết lập môi trường

Các lớp cần thiết để viết các bài kiểm tra sẽ được tìm thấy trong mô-đun 'đơn nhất'. Nếu bạn đang sử dụng các phiên bản Python cũ hơn (trước Python 2.1), mô-đun có thể được tải xuống từhttp://pyunit.sourceforge.net/. Tuy nhiên, mô-đun đơn nhất hiện là một phần của phân phối Python tiêu chuẩn; do đó nó không yêu cầu cài đặt riêng biệt.

'unittest' hỗ trợ tự động hóa thử nghiệm, chia sẻ mã thiết lập và tắt máy cho các thử nghiệm, tổng hợp các thử nghiệm thành bộ sưu tập và tính độc lập của các thử nghiệm khỏi khung báo cáo.

Mô-đun đơn nhất cung cấp các lớp giúp dễ dàng hỗ trợ những phẩm chất này cho một tập hợp các bài kiểm tra.

Để đạt được điều này, unittest hỗ trợ các khái niệm quan trọng sau:

  • test fixture- Điều này thể hiện sự chuẩn bị cần thiết để thực hiện một hoặc nhiều thử nghiệm và bất kỳ hành động dọn dẹp liên quan nào. Điều này có thể bao gồm, ví dụ, tạo cơ sở dữ liệu tạm thời hoặc proxy, thư mục hoặc bắt đầu một quy trình máy chủ.

  • test case- Đây là đơn vị thử nghiệm nhỏ nhất. Điều này kiểm tra phản hồi cụ thể đối với một tập hợp đầu vào cụ thể. unittest cung cấp một lớp cơ sở,TestCase, có thể được sử dụng để tạo các trường hợp thử nghiệm mới.

  • test suite- Đây là tập hợp các trường hợp thử nghiệm, bộ thử nghiệm hoặc cả hai. Điều này được sử dụng để tổng hợp các bài kiểm tra nên được thực hiện cùng nhau. Các bộ thử nghiệm được thực hiện bởi lớp TestSuite.

  • test runner- Đây là một thành phần điều phối việc thực hiện các bài kiểm tra và cung cấp kết quả cho người dùng. Người chạy có thể sử dụng giao diện đồ họa, giao diện văn bản hoặc trả về một giá trị đặc biệt để biểu thị kết quả thực hiện các bài kiểm tra.

Tạo bài kiểm tra đơn vị

Các bước sau đây liên quan đến việc viết một bài kiểm tra đơn vị đơn giản -

Step 1 - Nhập mô-đun mới nhất trong chương trình của bạn.

Step 2- Xác định một chức năng được kiểm tra. Trong ví dụ sau, hàm add () sẽ được kiểm tra.

Step 3 - Tạo testcase bằng cách phân lớp unittest.TestCase.

Step 4- Định nghĩa một bài kiểm tra như một phương thức bên trong lớp. Tên của phương thức phải bắt đầu bằng 'test'.

Step 5- Mỗi kiểm tra gọi chức năng khẳng định của lớp TestCase. Có nhiều loại khẳng định. Ví dụ sau đây gọi hàm khẳng địnhEquals ().

Step 6 - Hàm khẳng địnhEquals () so sánh kết quả của hàm add () với đối số arg2 và ném ra hàm khẳng địnhError nếu so sánh không thành công.

Step 7 - Cuối cùng, gọi phương thức main () từ mô-đun đơn nhất.

import unittest
def add(x,y):
   return x + y
   
class SimpleTest(unittest.TestCase):
   def testadd1(self):
      self.assertEquals(add(4,5),9)
      
if __name__ == '__main__':
   unittest.main()

Step 8 - Chạy đoạn script trên từ dòng lệnh.

C:\Python27>python SimpleTest.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK

Step 9 - Ba kết quả sau đây có thể là kết quả có thể có của một bài kiểm tra -

Sr.No Tin nhắn & Mô tả
1

OK

Thử nghiệm vượt qua. 'A' được hiển thị trên bảng điều khiển.

2

FAIL

Kiểm tra không vượt qua và đặt ra một ngoại lệ AssertionError. 'F' được hiển thị trên bảng điều khiển.

3

ERROR

Kiểm tra nêu ra một ngoại lệ khác với AssertionError. 'E' được hiển thị trên bảng điều khiển.

Các kết quả này được hiển thị trên bảng điều khiển theo thứ tự '.', 'F' và 'E'.

Giao diện dòng lệnh

Mô-đun đơn nhất có thể được sử dụng từ dòng lệnh để chạy một hoặc nhiều bài kiểm tra.

python -m unittest test1
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method

unittest hỗ trợ các tùy chọn dòng lệnh sau. Để có danh sách tất cả các tùy chọn dòng lệnh, hãy sử dụng lệnh sau:

Python –m unittest -h

Sr.No Tùy chọn & Mô tả
1

-h, --help

Hiển thị tin nhắn này

2

v, --verbose

Báo cáo dài dòng

3

-q, --quiet

Sản lượng tối thiểu

4

-f, --failfast

Dừng lại khi thất bại đầu tiên

5

-c, --catch

Bắt điều khiển-C và hiển thị kết quả

6

-b, --buffer

Bộ đệm stdout và stderr trong quá trình chạy thử nghiệm

Chương này thảo luận về các lớp và phương thức được định nghĩa trong mô-đun đơn nhất. Có năm lớp chính trong mô-đun này.

Lớp TestCase

Đối tượng của lớp này đại diện cho đơn vị nhỏ nhất có thể kiểm tra được. Nó nắm giữ các quy trình kiểm tra và cung cấp các móc để chuẩn bị từng quy trình và để dọn dẹp sau đó.

Các phương thức sau được định nghĩa trong lớp TestCase:

Sr.No Phương pháp & Mô tả
1

setUp()

Phương pháp được gọi để chuẩn bị vật cố định thử nghiệm. Điều này được gọi ngay lập tức trước khi gọi phương thức kiểm tra

2

tearDown()

Phương thức được gọi ngay sau khi phương thức thử được gọi và kết quả được ghi lại. Điều này được gọi là ngay cả khi phương pháp thử nghiệm đưa ra một ngoại lệ,

3

setUpClass()

Một phương thức lớp được gọi trước khi chạy thử nghiệm trong một lớp riêng lẻ.

4

tearDownClass()

Một phương thức lớp được gọi sau khi các bài kiểm tra trong một lớp riêng lẻ đã chạy.

5

run(result = None)

Chạy thử nghiệm, thu thập kết quả vào đối tượng kết quả thử nghiệm được thông qua kết quả .

6

skipTest(reason)

Gọi điều này trong một phương thức kiểm tra hoặc setUp () bỏ qua kiểm tra hiện tại.

7

debug()

Chạy thử nghiệm mà không thu thập kết quả.

số 8

shortDescription()

Trả về mô tả một dòng của bài kiểm tra.

Đồ đạc

Có thể có nhiều bài kiểm tra được viết bên trong một lớp TestCase. Các phương pháp kiểm tra này có thể cần kết nối cơ sở dữ liệu, tệp tạm thời hoặc các tài nguyên khác để được khởi tạo. Chúng được gọi là đồ đạc. TestCase bao gồm một móc đặc biệt để định cấu hình và dọn dẹp bất kỳ đồ đạc nào cần thiết cho các thử nghiệm của bạn. Để định cấu hình đồ đạc, hãy ghi đè setUp (). Để dọn dẹp, hãy ghi đè lên xé ráchDown ().

Trong ví dụ sau, hai bài kiểm tra được viết bên trong lớp TestCase. Họ kiểm tra kết quả của phép cộng và phép trừ hai giá trị. Phương thức setup () khởi tạo các đối số dựa trên shortDescription () của mỗi bài kiểm tra. Phương thức teardown () sẽ được thực thi vào cuối mỗi lần kiểm tra.

import unittest

class simpleTest2(unittest.TestCase):
   def setUp(self):
      self.a = 10
      self.b = 20
      name = self.shortDescription()
      if name == "Add":
         self.a = 10
         self.b = 20
         print name, self.a, self.b
      if name == "sub":
         self.a = 50
         self.b = 60
         print name, self.a, self.b
   def tearDown(self):
      print '\nend of test',self.shortDescription()

   def testadd(self):
      """Add"""
      result = self.a+self.b
      self.assertTrue(result == 100)
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)
      
if __name__ == '__main__':
   unittest.main()

Chạy đoạn mã trên từ dòng lệnh. Nó cho kết quả sau:

C:\Python27>python test2.py
Add 10 20
F
end of test Add
sub 50 60
end of test sub
.
================================================================
FAIL: testadd (__main__.simpleTest2)
Add
----------------------------------------------------------------------
Traceback (most recent call last):
   File "test2.py", line 21, in testadd
      self.assertTrue(result == 100)
AssertionError: False is not true
----------------------------------------------------------------------
Ran 2 tests in 0.015s

FAILED (failures = 1)

Lịch thi đấu lớp

Lớp TestCase có một phương thức setUpClass () có thể được ghi đè để thực thi trước khi thực hiện các bài kiểm tra riêng lẻ bên trong một lớp TestCase. Tương tự, phương thức ráchDownClass () sẽ được thực thi sau tất cả các lần kiểm tra trong lớp. Cả hai phương thức đều là phương thức lớp. Do đó, chúng phải được trang trí bằng chỉ thị @classmethod.

Ví dụ sau minh họa việc sử dụng các phương thức lớp này:

import unittest

class TestFixtures(unittest.TestCase):

   @classmethod
   def setUpClass(cls):
      print 'called once before any tests in class'

   @classmethod
   def tearDownClass(cls):
      print '\ncalled once after all tests in class'

   def setUp(self):
      self.a = 10
      self.b = 20
      name = self.shortDescription()
      print '\n',name
   def tearDown(self):
      print '\nend of test',self.shortDescription()

   def test1(self):
      """One"""
      result = self.a+self.b
      self.assertTrue(True)
   def test2(self):
      """Two"""
      result = self.a-self.b
      self.assertTrue(False)
      
if __name__ == '__main__':
unittest.main()

Lớp TestSuite

Khung thử nghiệm của Python cung cấp một cơ chế hữu ích mà theo đó các trường hợp thử nghiệm có thể được nhóm lại với nhau theo các tính năng mà chúng thử nghiệm. Cơ chế này được tạo sẵn bởi lớp TestSuite trong mô-đun đơn nhất.

Các bước sau đây liên quan đến việc tạo và chạy bộ thử nghiệm.

Step 1 - Tạo một thể hiện của lớp TestSuite.

suite = unittest.TestSuite()

Step 2 - Thêm các bài kiểm tra bên trong một lớp TestCase trong bộ.

suite.addTest(testcase class)

Step 3 - Bạn cũng có thể sử dụng phương thức makeSuite () để thêm các bài kiểm tra từ một lớp

suite = unittest.makeSuite(test case class)

Step 4 - Các bài kiểm tra cá nhân cũng có thể được thêm vào trong bộ.

suite.addTest(testcaseclass(""testmethod")

Step 5 - Tạo một đối tượng của lớp TestTestRunner.

runner = unittest.TextTestRunner()

Step 6 - Gọi phương thức run () để chạy tất cả các bài kiểm tra trong bộ

runner.run (suite)

Các phương thức sau được định nghĩa trong lớp TestSuite:

Sr.No Phương pháp & Mô tả
1

addTest()

Thêm một phương pháp thử nghiệm trong bộ thử nghiệm.

2

addTests()

Thêm các bài kiểm tra từ nhiều lớp TestCase.

3

run()

Chạy các bài kiểm tra được liên kết với bộ phần mềm này, thu thập kết quả vào đối tượng kết quả kiểm tra

4

debug()

Chạy các bài kiểm tra được liên kết với bộ phần mềm này mà không thu thập kết quả.

5

countTestCases()

Trả về số lượng thử nghiệm được đại diện bởi đối tượng thử nghiệm này

Ví dụ sau đây cho thấy cách sử dụng lớp TestSuite:

import unittest
class suiteTest(unittest.TestCase):
   def setUp(self):
      self.a = 10
      self.b = 20
      
   def testadd(self):
      """Add"""
      result = self.a+self.b
      self.assertTrue(result == 100)
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)
      
def suite():
   suite = unittest.TestSuite()
##   suite.addTest (simpleTest3("testadd"))
##   suite.addTest (simpleTest3("testsub"))
   suite.addTest(unittest.makeSuite(simpleTest3))
   return suite
   
if __name__ == '__main__':
   runner = unittest.TextTestRunner()
   test_suite = suite()
   runner.run (test_suite)

Bạn có thể thử nghiệm với phương thức addTest () bằng cách bỏ ghi chú các dòng và câu lệnh bình luận có phương thức makeSuite ().

Lớp TestLoader

Gói mới nhất có lớp TestLoader được sử dụng để tạo các bộ thử nghiệm từ các lớp và mô-đun. Theo mặc định, thể hiện unittest.defaultTestLoader được tạo tự động khi phương thức unittest.main (0 được gọi. Tuy nhiên, một thể hiện rõ ràng cho phép tùy chỉnh các thuộc tính nhất định.

Trong đoạn mã sau, các bài kiểm tra từ hai lớp được thu thập trong một Danh sách bằng cách sử dụng đối tượng TestLoader.

import unittest
testList = [Test1, Test2]
testLoad = unittest.TestLoader()

TestList = []
for testCase in testList:
   testSuite = testLoad.loadTestsFromTestCase(testCase)
   TestList.append(testSuite)
   
newSuite = unittest.TestSuite(TestList)
runner = unittest.TextTestRunner()
runner.run(newSuite)

Bảng sau đây hiển thị danh sách các phương thức trong lớp TestLoader:

S.Không Phương pháp & Mô tả
1

loadTestsFromTestCase()

Trả về một bộ tất cả các trường hợp kiểm thử có trong một lớp TestCase

2

loadTestsFromModule()

Trả về một bộ tất cả các trường hợp kiểm tra có trong mô-đun đã cho.

3

loadTestsFromName()

Trả về một tập hợp tất cả các trường hợp kiểm tra được cung cấp một trình xác định chuỗi.

4

discover()

Tìm tất cả các mô-đun thử nghiệm bằng cách đệ quy vào các thư mục con từ thư mục bắt đầu được chỉ định và trả về một đối tượng TestSuite

Lớp TestResult

Lớp này được sử dụng để biên dịch thông tin về các bài kiểm tra đã thành công và các bài kiểm tra gặp thất bại. Một đối tượng TestResult lưu trữ kết quả của một tập hợp các bài kiểm tra. Một cá thể TestResult được trả về bởi phương thức TestRunner.run ().

Các phiên bản TestResult có các thuộc tính sau:

Sr.No Thuộc tính & Mô tả
1

Errors

Một danh sách chứa 2 bộ dữ liệu TestCase và các chuỗi chứa các truy nguyên được định dạng. Mỗi bộ giá trị đại diện cho một bài kiểm tra đưa ra một ngoại lệ không mong muốn.

2

Failures

Một danh sách chứa 2 bộ dữ liệu TestCase và các chuỗi chứa các truy nguyên được định dạng. Mỗi tuple đại diện cho một bài kiểm tra trong đó lỗi được báo hiệu rõ ràng bằng cách sử dụng các phương thức TestCase.assert * ().

3

Skipped

Một danh sách chứa 2 bộ dữ liệu TestCase và các chuỗi chứa lý do bỏ qua bài kiểm tra.

4

wasSuccessful()

Trả về True nếu tất cả các thử nghiệm chạy cho đến nay đã trôi qua, nếu không trả về False.

5

stop()

Phương thức này có thể được gọi để báo hiệu rằng tập hợp các thử nghiệm đang được chạy nên được hủy bỏ.

6

startTestRun()

Được gọi một lần trước khi bất kỳ thử nghiệm nào được thực hiện.

7

stopTestRun()

Được gọi một lần sau khi tất cả các thử nghiệm được thực hiện.

số 8

testsRun

Tổng số thử nghiệm đã chạy cho đến nay.

9

Buffer

Nếu được đặt thành true, sys.stdoutsys.stderr sẽ được lưu vào bộ đệm giữa startTest () và stopTest () đang được gọi.

Đoạn mã sau thực thi một bộ thử nghiệm -

if __name__ == '__main__':
   runner = unittest.TextTestRunner()
   test_suite = suite()
   result = runner.run (test_suite)
   
   print "---- START OF TEST RESULTS"
   print result

   print "result::errors"
   print result.errors

   print "result::failures"
   print result.failures

   print "result::skipped"
   print result.skipped

   print "result::successful"
   print result.wasSuccessful()
   
   print "result::test-run"
   print result.testsRun
   print "---- END OF TEST RESULTS"

Mã khi được thực thi sẽ hiển thị đầu ra sau:

---- START OF TEST RESULTS
<unittest.runner.TextTestResult run = 2 errors = 0 failures = 1>
result::errors
[]
result::failures
[(<__main__.suiteTest testMethod = testadd>, 'Traceback (most recent call last):\n
   File "test3.py", line 10, in testadd\n 
   self.assertTrue(result == 100)\nAssert
   ionError: False is not true\n')]
result::skipped
[]
result::successful
False
result::test-run
2
---- END OF TEST RESULTS

Khung thử nghiệm Python sử dụng hàm khẳng định () tích hợp của Python để kiểm tra một điều kiện cụ thể. Nếu xác nhận không thành công, một AssertionError sẽ xuất hiện. Khung thử nghiệm sau đó sẽ xác định thử nghiệm là Không đạt. Các trường hợp ngoại lệ khác được coi là Lỗi.

Ba bộ hàm xác nhận sau được định nghĩa trong mô-đun đơn nhất:

  • Các cảnh báo Boolean cơ bản
  • Các cảnh báo so sánh
  • Thông báo cho Bộ sưu tập

Các hàm khẳng định cơ bản đánh giá kết quả của một phép toán là Đúng hay Sai. Tất cả các phương thức xác nhận đều chấp nhậnmsg đối số mà, nếu được chỉ định, được sử dụng làm thông báo lỗi khi không thành công.

Sr.No Phương pháp & Mô tả
1

assertEqual(arg1, arg2, msg = None)

Kiểm tra rằng arg1arg2 bằng nhau. Nếu các giá trị không so sánh bằng nhau, thử nghiệm sẽ không thành công.

2

assertNotEqual(arg1, arg2, msg = None)

Kiểm tra mà arg1arg2 không bằng nhau. Nếu các giá trị so sánh bằng nhau, thử nghiệm sẽ không thành công.

3

assertTrue(expr, msg = None)

Kiểm tra rằng expr là đúng. Nếu sai, kiểm tra không thành công

4

assertFalse(expr, msg = None)

Kiểm tra rằng expr là sai. Nếu đúng, kiểm tra không thành công

5

assertIs(arg1, arg2, msg = None)

Thử nghiệm mà arg1arg2 đánh giá cho cùng một đối tượng.

6

assertIsNot(arg1, arg2, msg = None)

Kiểm tra arg1arg2 không đánh giá cùng một đối tượng.

7

assertIsNone(expr, msg = None)

Kiểm tra rằng expr là Không. Nếu không Không, kiểm tra không thành công

số 8

assertIsNotNone(expr, msg = None)

Kiểm tra rằng expr không phải là Không. Nếu không, kiểm tra không thành công

9

assertIn(arg1, arg2, msg = None)

Kiểm tra arg1 trong arg2 .

10

assertNotIn(arg1, arg2, msg = None)

Kiểm tra arg1 không có trong arg2 .

11

assertIsInstance(obj, cls, msg = None)

Kiểm tra xem obj là một ví dụ của cls

12

assertNotIsInstance(obj, cls, msg = None)

Kiểm tra xem obj không phải là một trường hợp của cls

Một số hàm khẳng định ở trên được thực hiện trong đoạn mã sau:

import unittest

class SimpleTest(unittest.TestCase):
   def test1(self):
      self.assertEqual(4 + 5,9)
   def test2(self):
      self.assertNotEqual(5 * 2,10)
   def test3(self):
      self.assertTrue(4 + 5 == 9,"The result is False")
   def test4(self):
      self.assertTrue(4 + 5 == 10,"assertion fails")
   def test5(self):
      self.assertIn(3,[1,2,3])
   def test6(self):
      self.assertNotIn(3, range(5))

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

Khi tập lệnh trên được chạy, test2, test4 và test6 sẽ hiển thị lỗi và các tập lệnh khác chạy thành công.

FAIL: test2 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python27\SimpleTest.py", line 9, in test2
      self.assertNotEqual(5*2,10)
AssertionError: 10 == 10

FAIL: test4 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python27\SimpleTest.py", line 13, in test4
      self.assertTrue(4+5==10,"assertion fails")
AssertionError: assertion fails

FAIL: test6 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python27\SimpleTest.py", line 17, in test6
      self.assertNotIn(3, range(5))
AssertionError: 3 unexpectedly found in [0, 1, 2, 3, 4]

----------------------------------------------------------------------            
Ran 6 tests in 0.001s                                                             
                                                                                  
FAILED (failures = 3)

Tập hợp các hàm khẳng định thứ hai là comparative asserts −

  • assertAlmostEqual (đầu tiên, thứ hai, vị trí = 7, msg = Không có, delta = Không có)

    Kiểm tra rằng đầu tiênthứ hai là xấp xỉ (hoặc không ước tính) bằng bằng cách tính toán sự khác biệt, làm tròn đến số lượng nhất định của số thập phân nơi (mặc định 7),

  • assertNotAlmostEqual (đầu tiên, thứ hai, địa điểm, tin nhắn, đồng bằng)

    Kiểm tra xem thứ nhất và thứ hai không xấp xỉ bằng nhau bằng cách tính toán sự khác biệt, làm tròn đến số chữ số thập phân đã cho (mặc định là 7) và so sánh với số không.

    Trong cả hai hàm trên, nếu delta được cung cấp thay vì địa điểm thì hiệu số giữa thứ nhất và thứ hai phải nhỏ hơn hoặc bằng (hoặc lớn hơn) delta.

    Việc cung cấp cả vùng đồng bằng và địa điểm làm tăng TypeError.

  • assertGreater (đầu tiên, thứ hai, msg = Không có)

    Kiểm tra đầu tiên lớn hơn thứ hai tùy thuộc vào tên phương pháp. Nếu không, bài kiểm tra sẽ thất bại.

  • assertGreaterEqual (đầu tiên, thứ hai, msg = Không có)

    Kiểm tra đầu tiên lớn hơn hoặc bằng thứ hai tùy thuộc vào tên phương pháp. Nếu không, bài kiểm tra sẽ không thành công

  • assertLess (đầu tiên, thứ hai, msg = Không có)

    Thử nghiệm đầu tiên ít hơn thứ hai tùy thuộc vào tên phương pháp. Nếu không, bài kiểm tra sẽ không thành công

  • assertLessEqual (đầu tiên, thứ hai, msg = Không có)

    Kiểm tra đầu tiên nhỏ hơn hoặc bằng thứ hai tùy thuộc vào tên phương pháp. Nếu không, bài kiểm tra sẽ thất bại.

  • assertRegexpMatches (text, regexp, msg = Không có)

    Kiểm tra xem tìm kiếm regexp có khớp với văn bản không. Trong trường hợp không thành công, thông báo lỗi sẽ bao gồm mẫu và văn bản. regexp có thể là một đối tượng biểu thức chính quy hoặc một chuỗi chứa một biểu thức chính quy phù hợp để sử dụng bởire.search().

  • assertNotRegexpMatches (text, regexp, msg = Không có)

    Xác minh rằng tìm kiếm regexp không khớp với văn bản . Không có thông báo lỗi bao gồm mẫu và phần văn bản khớp. regexp có thể là một đối tượng biểu thức chính quy hoặc một chuỗi chứa một biểu thức chính quy phù hợp để sử dụng bởire.search().

Các chức năng khẳng định được thực hiện trong ví dụ sau:

import unittest
import math
import re

class SimpleTest(unittest.TestCase):
   def test1(self):
      self.assertAlmostEqual(22.0/7,3.14)
   def test2(self):
      self.assertNotAlmostEqual(10.0/3,3)
   def test3(self):
      self.assertGreater(math.pi,3)
   def test4(self):
      self.assertNotRegexpMatches("Tutorials Point (I) Private Limited","Point")

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

Tập lệnh trên báo cáo test1 và test4 là Không thành công. Trong test1, phép chia của 22/7 không nằm trong 7 chữ số thập phân của 3,14. Tương tự, vì đối số thứ hai khớp với văn bản trong đối số đầu tiên, kết quả test4 là AssertionError.

=====================================================FAIL: test1 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 7, in test1
      self.assertAlmostEqual(22.0/7,3.14)
AssertionError: 3.142857142857143 != 3.14 within 7 places
================================================================
FAIL: test4 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 13, in test4
      self.assertNotRegexpMatches("Tutorials Point (I) Private Limited","Point")
AssertionError: Regexp matched: 'Point' matches 'Point' in 'Tutorials Point (I)
Private Limited'
----------------------------------------------------------------------

Ran 4 tests in 0.001s                                                             
                                                                                  
FAILED (failures = 2)

Khẳng định cho Bộ sưu tập

Tập hợp các hàm khẳng định này được sử dụng với các kiểu dữ liệu thu thập trong Python, chẳng hạn như Danh sách, Tuple, Từ điển và Tập hợp.

Sr.No Phương pháp & Mô tả
1

assertListEqual (list1, list2, msg = None)

Kiểm tra mà hai danh sách bằng nhau. Nếu không, một thông báo lỗi được xây dựng chỉ hiển thị sự khác biệt giữa hai thông báo.

2

assertTupleEqual (tuple1, tuple2, msg = None)

Kiểm tra hai bộ giá trị bằng nhau. Nếu không, một thông báo lỗi được xây dựng chỉ hiển thị sự khác biệt giữa hai thông báo.

3

assertSetEqual (set1, set2, msg = None)

Kiểm tra mà hai tập hợp bằng nhau. Nếu không, một thông báo lỗi được xây dựng liệt kê sự khác biệt giữa các tập hợp.

4

assertDictEqual (expected, actual, msg = None)

Kiểm tra xem hai từ điển bằng nhau. Nếu không, một thông báo lỗi sẽ được tạo ra để hiển thị sự khác biệt trong các từ điển.

Ví dụ sau đây thực hiện các phương pháp trên:

import unittest

class SimpleTest(unittest.TestCase):
   def test1(self):
      self.assertListEqual([2,3,4], [1,2,3,4,5])
   def test2(self):
      self.assertTupleEqual((1*2,2*2,3*2), (2,4,6))
   def test3(self):
      self.assertDictEqual({1:11,2:22},{3:33,2:22,1:11})

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

Trong ví dụ trên, test1 và test3 hiển thị AssertionError. Thông báo lỗi hiển thị sự khác biệt trong các đối tượng Danh sách và Từ điển.

FAIL: test1 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 5, in test1
      self.assertListEqual([2,3,4], [1,2,3,4,5])
AssertionError: Lists differ: [2, 3, 4] != [1, 2, 3, 4, 5]

First differing element 0:
2
1

Second list contains 2 additional elements.
First extra element 3:
4

- [2, 3, 4]
+ [1, 2, 3, 4, 5]
? +++       +++

FAIL: test3 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 9, in test3
      self.assertDictEqual({1:11,2:22},{3:33,2:22,1:11})
AssertionError: {1: 11, 2: 22} != {1: 11, 2: 22, 3: 33}
- {1: 11, 2: 22}
+ {1: 11, 2: 22, 3: 33}
?              +++++++
                                                                                  
----------------------------------------------------------------------            
Ran 3 tests in 0.001s                                                             
                                                                                  
FAILED (failures = 2)

Lớp TestLoader có hàm explore (). Khung thử nghiệm Python sử dụng điều này để khám phá thử nghiệm đơn giản. Để tương thích, các mô-đun và gói chứa các bài kiểm tra phải có thể nhập được từ thư mục cấp cao nhất.

Sau đây là cách sử dụng dòng lệnh cơ bản của khám phá thử nghiệm:

Python –m unittest discover

Trình thông dịch cố gắng tải tất cả các mô-đun chứa thử nghiệm từ thư mục hiện tại và các thư mục bên trong một cách đệ quy. Các tùy chọn dòng lệnh khác là -

Sr.No Tùy chọn & Mô tả
1

-v, --verbose

Báo cáo dài dòng

2

-s, --start-directory

thư mục Thư mục để bắt đầu khám phá (. mặc định)

3

-p, --pattern

Mẫu mẫu để khớp với các tệp thử nghiệm (mặc định thử nghiệm * .py)

4

-t, --top-level-directory

thư mục Thư mục cấp cao nhất của dự án (mặc định là thư mục bắt đầu)

Ví dụ: để khám phá các bài kiểm tra trong các mô-đun có tên bắt đầu bằng 'khẳng định' trong thư mục 'kiểm tra', dòng lệnh sau được sử dụng:

C:\python27>python –m unittest –v –s "c:\test" –p "assert*.py"

Khám phá thử nghiệm tải các thử nghiệm bằng cách nhập chúng. Khi kiểm tra phát hiện đã tìm thấy tất cả các tệp kiểm tra từ thư mục bắt đầu mà bạn chỉ định, nó sẽ biến các đường dẫn thành tên gói để nhập.

Nếu bạn cung cấp thư mục bắt đầu dưới dạng tên gói thay vì đường dẫn đến thư mục thì khám phá giả định rằng bất kỳ vị trí nào mà nó nhập từ là vị trí bạn dự định, vì vậy bạn sẽ không nhận được cảnh báo.

Hỗ trợ bỏ qua các bài kiểm tra đã được thêm vào kể từ Python 2.7. Có thể bỏ qua phương pháp kiểm tra riêng lẻ hoặc lớp TestCase, có điều kiện cũng như vô điều kiện. Khuôn khổ cho phép một thử nghiệm nhất định được đánh dấu là 'thất bại dự kiến'. Thử nghiệm này sẽ 'thất bại' nhưng sẽ không được tính là không thành công trong TestResult.

Để bỏ qua một phương thức vô điều kiện, phương thức lớp unittest.skip () sau có thể được sử dụng:

import unittest

   def add(x,y):
      return x+y

class SimpleTest(unittest.TestCase):
   @unittest.skip("demonstrating skipping")
   def testadd1(self):
      self.assertEquals(add(4,5),9)

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

Vì bỏ qua () là một phương thức của lớp, nó có tiền tố là @ token. Phương thức nhận một đối số: một thông báo nhật ký mô tả lý do bỏ qua.

Khi tập lệnh trên được thực thi, kết quả sau được hiển thị trên bảng điều khiển:

C:\Python27>python skiptest.py
s
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK (skipped = 1)

Ký tự 's' chỉ ra rằng một bài kiểm tra đã bị bỏ qua.

Cú pháp thay thế cho việc bỏ qua kiểm tra là sử dụng phương thức instance jumpTest () bên trong hàm kiểm tra.

def testadd2(self):
   self.skipTest("another method for skipping")
   self.assertTrue(add(4 + 5) == 10)

Các trình trang trí sau thực hiện bỏ qua thử nghiệm và các lỗi dự kiến:

Sr.No Phương pháp & Mô tả
1

unittest.skip(reason)

Bỏ qua bài kiểm tra được trang trí một cách vô điều kiện. lý do nên mô tả lý do tại sao thử nghiệm bị bỏ qua.

2

unittest.skipIf(condition, reason)

Bỏ qua thử nghiệm trang trí nếu điều kiện là đúng.

3

unittest.skipUnless(condition, reason)

Bỏ qua thử nghiệm được trang trí trừ khi điều kiện là đúng.

4

unittest.expectedFailure()

Đánh dấu bài kiểm tra là một thất bại dự kiến. Nếu thử nghiệm không đạt khi chạy, thử nghiệm không được tính là thất bại.

Ví dụ sau minh họa việc sử dụng bỏ qua có điều kiện và thất bại dự kiến.

import unittest

class suiteTest(unittest.TestCase):
   a = 50
   b = 40
   
   def testadd(self):
      """Add"""
      result = self.a+self.b
      self.assertEqual(result,100)

   @unittest.skipIf(a>b, "Skip over this routine")
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)
   
   @unittest.skipUnless(b == 0, "Skip over this routine")
   def testdiv(self):
      """div"""
      result = self.a/self.b
      self.assertTrue(result == 1)

   @unittest.expectedFailure
   def testmul(self):
      """mul"""
      result = self.a*self.b
      self.assertEqual(result == 0)

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

Trong ví dụ trên, testsub () và testdiv () sẽ bị bỏ qua. Trong trường hợp đầu tiên a> b là đúng, trong khi trong trường hợp thứ hai b == 0 là không đúng. Mặt khác, testmul () đã được đánh dấu là không thành công.

Khi tập lệnh trên được chạy, hai kiểm tra bị bỏ qua hiển thị là 's' và lỗi dự kiến ​​được hiển thị là 'x'.

C:\Python27>python skiptest.py
Fsxs
================================================================
FAIL: testadd (__main__.suiteTest)
Add
----------------------------------------------------------------------
Traceback (most recent call last):
   File "skiptest.py", line 9, in testadd
      self.assertEqual(result,100)
AssertionError: 90 != 100

----------------------------------------------------------------------
Ran 4 tests in 0.000s

FAILED (failures = 1, skipped = 2, expected failures = 1)

Khung thử nghiệm Python cung cấp các phương pháp xác nhận sau để kiểm tra xem có các ngoại lệ được đưa ra hay không.

khẳng địnhRaises (ngoại lệ, có thể gọi, * args, ** kwds)

Kiểm tra xem một ngoại lệ (đối số đầu tiên) được đưa ra khi một hàm được gọi với bất kỳ đối số vị trí hoặc từ khóa nào. Kiểm tra sẽ vượt qua nếu ngoại lệ mong đợi được nâng lên, là một lỗi nếu một ngoại lệ khác được đưa ra hoặc không thành công nếu không có ngoại lệ nào được nêu ra. Để bắt bất kỳ nhóm ngoại lệ nào, một tuple chứa các lớp ngoại lệ có thể được chuyển làm ngoại lệ.

Trong ví dụ dưới đây, một hàm kiểm tra được định nghĩa để kiểm tra xem ZeroDivisionError có được nâng lên hay không.

import unittest

def div(a,b):
   return a/b
class raiseTest(unittest.TestCase):
   def testraise(self):
      self.assertRaises(ZeroDivisionError, div, 1,0)

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

Hàm testraise () sử dụng hàm khẳng định () để xem liệu phép chia cho 0 có xảy ra khi hàm div () được gọi hay không. Đoạn mã trên sẽ nêu ra một ngoại lệ. Nhưng thay đổi các đối số thành hàm div () như sau:

self.assertRaises(ZeroDivisionError, div, 1,1)

Khi một mã được chạy với những thay đổi này, kiểm tra không thành công vì ZeroDivisionError không xảy ra.

F
================================================================
FAIL: testraise (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "raisetest.py", line 7, in testraise
      self.assertRaises(ZeroDivisionError, div, 1,1)
AssertionError: ZeroDivisionError not raised

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

FAILED (failures = 1)

khẳng địnhRaisesRegexp (ngoại lệ, regexp, có thể gọi, * args, ** kwds)

Kiểm tra regexp khớp với biểu diễn chuỗi của ngoại lệ đã nêu. regexp có thể là một đối tượng biểu thức chính quy hoặc một chuỗi chứa một biểu thức chính quy phù hợp để re.search () sử dụng.

Ví dụ sau đây cho thấy cách khẳng địnhRaisesRegexp () được sử dụng:

import unittest
import re

class raiseTest(unittest.TestCase):
   def testraiseRegex(self):
      self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","TutorialsPoint")
      
if __name__ == '__main__':
   unittest.main()

Ở đây, kiểm tra testraseRegex () không thất bại như đối số đầu tiên. "Điểm" được tìm thấy trong chuỗi đối số thứ hai.

================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:/Python27/raiseTest.py", line 11, in testraiseRegex
      self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","TutorialsPoint")
AssertionError: TypeError not raised
----------------------------------------------------------------------

Tuy nhiên, sự thay đổi như hình dưới đây -

self.assertRaisesRegexp(TypeError, "invalid", reg,123,"TutorialsPoint")

Ngoại lệ TypeError sẽ được ném ra. Do đó, kết quả sau sẽ được hiển thị:

================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "raisetest.py", line 11, in testraiseRegex
      self.assertRaisesRegexp(TypeError, "invalid", reg,123,"TutorialsPoint")
AssertionError: "invalid" does not match 
   "first argument must be string or compiled pattern"
----------------------------------------------------------------------

Junit, khuôn khổ kiểm thử đơn vị Java (Pyunit đang triển khai JUnit) có một tùy chọn thời gian chờ tiện dụng. Nếu một bài kiểm tra kéo dài hơn thời gian quy định, nó sẽ bị đánh dấu là không đạt.

Khung thử nghiệm của Python không chứa bất kỳ hỗ trợ nào cho thời gian chờ. Tuy nhiên, một mô-đun phần thứ ba được gọi là timeout-decorator có thể thực hiện công việc.

Tải xuống và cài đặt mô-đun từ -

https://pypi.python.org/packages/source/t/timeout-decorator/timeout-decorator-0.3.2.tar.gz

  • Nhập timeout_decorator vào mã
  • Đặt trang trí thời gian chờ trước khi kiểm tra
  • @timeout_decorator.timeout(10)

Nếu phương pháp kiểm tra bên dưới dòng này mất nhiều hơn thời gian chờ được đề cập (10 phút) ở đây, lỗi TimeOutError sẽ xuất hiện. Ví dụ -

import time
import timeout_decorator

class timeoutTest(unittest.TestCase):

   @timeout_decorator.timeout(5)
   def testtimeout(self):
      print "Start"
   for i in range(1,10):
      time.sleep(1)
      print "%d seconds have passed" % i
      
if __name__ == '__main__':
   unittest.main()

unittest2 là một nền tảng hỗ trợ các tính năng bổ sung được thêm vào khung thử nghiệm Python trong Python 2.7 trở đi. Nó được thử nghiệm để chạy trên Python 2.6, 2.7 và 3. *. Phiên bản mới nhất có thể được tải xuống từhttps://pypi.python.org/pypi/unittest2

Để sử dụng unittest2 thay vì unittest, chỉ cần thay thế import unittest bằng import unittest2.

Các lớp trong unittest2 bắt nguồn từ các lớp thích hợp trong unittest, vì vậy có thể sử dụng cơ sở hạ tầng chạy thử nghiệm unittest2 mà không cần phải chuyển tất cả các thử nghiệm của bạn sang sử dụng unittest2 ngay lập tức. Trong trường hợp bạn định triển khai các tính năng mới, hãy phân lớp testcase của bạn từunittest2.TestCase thay vì unittest.TestCase

Sau đây là các tính năng mới của unittest2 -

  • addCleanups để quản lý tài nguyên tốt hơn

  • Chứa nhiều phương pháp xác nhận mới

  • assertRaises với tư cách là người quản lý ngữ cảnh, sau đó có quyền truy cập vào ngoại lệ

  • Có đồ đạc cấp mô-đun chẳng hạn như setUpModuletearDownModule

  • Bao gồm load_tests giao thức để tải các bài kiểm tra từ các mô-đun hoặc gói

  • startTestRunstopTestRun phương pháp trên TestResult

Trong Python 2.7, bạn gọi các tính năng dòng lệnh đơn nhất (bao gồm cả khám phá thử nghiệm) với python -m unittest <args>.

Thay vào đó, unittest2 đi kèm với một đơn vị tập lệnh2.

unit2 discover
unit2 -v test_module

Việc xử lý điều khiển-C hiệu quả hơn trong quá trình chạy thử nghiệm được cung cấp bởi tùy chọn dòng lệnh -c / - catch để hợp nhất, cùng với catchbreaktham số. Với hành vi ngắt bắt được kích hoạt, control-C sẽ cho phép hoàn tất quá trình thử nghiệm hiện đang chạy và quá trình chạy thử nghiệm sau đó sẽ kết thúc và báo cáo tất cả kết quả cho đến nay. Điều khiển-c thứ hai sẽ nâng cao một KeyboardInterrupt theo cách thông thường.

Nếu trình xử lý đơn nhất được gọi nhưng trình xử lý signal.SIGINT chưa được cài đặt, thì trình xử lý này sẽ gọi trình xử lý mặc định. Đây thường sẽ là hành vi mong đợi bởi mã thay thế một trình xử lý đã cài đặt và ủy quyền cho nó. Đối với các bài kiểm tra riêng lẻ cần vô hiệu hóa việc xử lý control-c duy nhất, trình trang trí removeHandler () có thể được sử dụng.

Các chức năng tiện ích sau cho phép chức năng xử lý control-c trong các khung thử nghiệm:

unittest.installHandler ()

Cài đặt trình xử lý control-c. Khi mộtsignal.SIGINT được nhận tất cả các kết quả đã đăng ký có TestResult.stop () được gọi.

unittest.registerResult (kết quả)

Đăng ký một TestResultđối tượng để xử lý control-c. Đăng ký một kết quả lưu trữ một tham chiếu yếu đến nó, vì vậy nó không ngăn kết quả được thu thập rác.

unittest.removeResult (kết quả)

Xóa kết quả đã đăng ký. Khi một kết quả đã bị loại bỏ thì TestResult.stop () sẽ không còn được gọi trên đối tượng kết quả đó để phản hồi lại một điều khiển-c.

unittest.removeHandler (function = None)

Khi được gọi mà không có đối số, hàm này loại bỏ trình xử lý control-c nếu nó đã được cài đặt. Chức năng này cũng có thể được sử dụng như một trình trang trí thử nghiệm để tạm thời xóa trình xử lý trong khi thử nghiệm đang được thực hiện.

Trình chạy thử nghiệm GUI

Mô-đun độc nhất được cài đặt để khám phá và chạy các thử nghiệm một cách tương tác. Tiện ích này, một tập lệnh Python 'inittestgui.py' sử dụng mô-đun Tkinter là một cổng Python cho bộ công cụ đồ họa TK. Nó cung cấp một GUI dễ sử dụng để khám phá và chạy thử nghiệm.

Python unittestgui.py

Nhấp vào nút 'Khám phá Kiểm tra'. Một hộp thoại nhỏ xuất hiện nơi bạn có thể chọn thư mục và mô-đun để chạy thử nghiệm từ đó.

Cuối cùng, nhấp vào nút bắt đầu. Các bài kiểm tra sẽ được phát hiện từ các tên mô-đun và đường dẫn đã chọn và ngăn kết quả sẽ hiển thị kết quả.

Để xem chi tiết của bài kiểm tra cá nhân, hãy chọn và nhấp vào bài kiểm tra trong hộp kết quả -

Nếu bạn không tìm thấy tiện ích này trong cài đặt Python, bạn có thể lấy nó từ trang dự án http://pyunit.sourceforge.net/.

Tương tự, tiện ích dựa trên bộ công cụ wxpython cũng có sẵn ở đó.

Phân phối tiêu chuẩn của Python có chứa mô-đun 'Doctest'. Chức năng của mô-đun này giúp bạn có thể tìm kiếm các đoạn văn bản trông giống như các phiên Python tương tác và thực thi các phiên này để xem chúng có hoạt động chính xác như được hiển thị hay không.

Doctest có thể rất hữu ích trong các trường hợp sau:

  • Để kiểm tra xem các chuỗi tài liệu của mô-đun có được cập nhật hay không bằng cách xác minh rằng tất cả các ví dụ tương tác vẫn hoạt động như được ghi lại.

  • Để thực hiện kiểm tra hồi quy bằng cách xác minh rằng các ví dụ tương tác từ tệp thử nghiệm hoặc đối tượng thử nghiệm hoạt động như mong đợi.

  • Để viết tài liệu hướng dẫn cho một gói, được minh họa rõ ràng với các ví dụ đầu vào-đầu ra

Trong Python, 'docstring' là một chuỗi ký tự xuất hiện dưới dạng biểu thức đầu tiên trong một lớp, hàm hoặc mô-đun. Nó bị bỏ qua khi bộ được thực thi, nhưng nó được trình biên dịch nhận dạng và đưa vào__doc__thuộc tính của lớp, chức năng hoặc mô-đun bao quanh. Vì nó có sẵn thông qua xem xét nội tâm, nó là nơi chuẩn tắc cho tài liệu về đối tượng.

Một cách thông thường là đặt cách sử dụng ví dụ của các phần khác nhau của mã Python bên trong chuỗi docstring. Mô-đun học thuyết cho phép xác minh rằng các chuỗi tài liệu này được cập nhật với các bản sửa đổi không liên tục trong mã.

Trong đoạn mã sau, một hàm giai thừa được xác định xen kẽ với việc sử dụng ví dụ. Để xác minh xem cách sử dụng ví dụ có đúng hay không, hãy gọi hàm testmod () trong mô-đun doctest.

"""
This is the "example" module.

The example module supplies one function, factorial(). For example,

>>> factorial(5)
120
"""

def factorial(x):
   """Return the factorial of n, an exact integer >= 0.
   >>> factorial(-1)
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
   """
   
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testmod()

Nhập và lưu tập lệnh trên dưới dạng FactDocTest.py và cố gắng thực thi tập lệnh này từ dòng lệnh.

Python FactDocTest.py

Không có đầu ra nào được hiển thị trừ khi ví dụ không thành công. Bây giờ, hãy thay đổi dòng lệnh thành sau:

Python FactDocTest.py –v

Bảng điều khiển bây giờ sẽ hiển thị kết quả sau:

C:\Python27>python FactDocTest.py -v
Trying:
   factorial(5)
Expecting:
   120
ok
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
2 items passed all tests:
   1 tests in __main__
   1 tests in __main__.factorial
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

Mặt khác, nếu mã của hàm factorial () không cho kết quả như mong đợi trong docstring, kết quả lỗi sẽ được hiển thị. Ví dụ: thay f = 2 thay cho f = 1 trong tập lệnh trên và chạy lại học thuyết. Kết quả sẽ như sau:

Trying:
   factorial(5)
Expecting:
   120
**********************************************************************
File "docfacttest.py", line 6, in __main__
Failed example:
factorial(5)
Expected:
   120
Got:
   240
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
1 items passed all tests:
   1 tests in __main__.factorial
**********************************************************************
1 items had failures:
   1 of 1 in __main__
2 tests in 2 items.
1 passed and 1 failed.
***Test Failed*** 1 failures.

Doctest: Kiểm tra các ví dụ trong tệp văn bản

Một ứng dụng đơn giản khác của học thuyết là thử nghiệm các ví dụ tương tác trong tệp văn bản. Điều này có thể được thực hiện với hàm testfile ().

Văn bản sau được lưu trữ trong một tệp văn bản có tên 'example.txt'.

Using ''factorial''
-------------------
This is an example text file in reStructuredText format. First import
''factorial'' from the ''example'' module:
   >>> from example import factorial
Now use it:
   >>> factorial(5)
   120

Nội dung tệp được coi là docstring. Để xác minh các ví dụ trong tệp văn bản, hãy sử dụng hàm testfile () của mô-đun học thuyết.

def factorial(x):
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testfile("example.txt")
  • Như với testmod (), testfile () sẽ không hiển thị bất cứ thứ gì trừ khi một ví dụ không thành công. Nếu một ví dụ không thành công, thì (các) ví dụ không thành công và (các) nguyên nhân của (các) lỗi sẽ được in ra bảng điều khiển, sử dụng định dạng giống như testmod ().

  • Trong hầu hết các trường hợp, việc sao chép và dán phiên bảng điều khiển tương tác hoạt động tốt, nhưng doctest không cố gắng thực hiện mô phỏng chính xác bất kỳ trình bao Python cụ thể nào.

  • Bất kỳ đầu ra dự kiến ​​nào phải ngay lập tức theo dòng cuối cùng '>>>' hoặc '...' chứa mã và đầu ra dự kiến ​​(nếu có) kéo dài đến dòng tiếp theo '>>>' hoặc toàn bộ khoảng trắng.

  • Đầu ra mong đợi không được chứa dòng toàn khoảng trắng, vì dòng này được sử dụng để báo hiệu kết thúc đầu ra dự kiến. Nếu đầu ra mong đợi chứa một dòng trống, hãy đặt <BLANKLINE> trong ví dụ tài liệu của bạn, mỗi nơi một dòng trống được mong đợi.

API doctest xoay quanh hai lớp vùng chứa sau được sử dụng để lưu trữ các ví dụ tương tác từ docstrings:

  • Example - Một câu lệnh Python duy nhất, được ghép nối với đầu ra dự kiến ​​của nó.

  • DocTest - Một tập hợp các Ví dụ, thường được trích xuất từ ​​một chuỗi tài liệu hoặc một tệp văn bản.

Các lớp xử lý bổ sung sau được xác định để tìm, phân tích cú pháp và chạy cũng như kiểm tra các ví dụ về học thuyết -

  • DocTestFinder - Tìm tất cả các chuỗi tài liệu trong một mô-đun nhất định và sử dụng một DocTestParser để tạo một DocTest từ mọi chuỗi tài liệu có chứa các ví dụ tương tác.

  • DocTestParser - Tạo một đối tượng học thuyết từ một chuỗi (chẳng hạn như chuỗi tài liệu của một đối tượng).

  • DocTestRunner - Thực thi các ví dụ trong một học thuyết và sử dụng Công cụ kiểm tra đầu ra để xác minh đầu ra của chúng.

  • OutputChecker - So sánh đầu ra thực tế từ một ví dụ về học thuyết với đầu ra dự kiến ​​và quyết định xem chúng có khớp hay không.

Lớp DocTestFinder

Nó là một lớp xử lý được sử dụng để trích xuất các học thuyết có liên quan đến một đối tượng nhất định, từ chuỗi doc của nó và các chuỗi tài liệu của các đối tượng chứa nó. Doctests hiện có thể được trích xuất từ ​​các kiểu đối tượng sau - mô-đun, hàm, lớp, phương thức, staticmethods, classmethods và thuộc tính.

Lớp này định nghĩa phương thức find (). Nó trả về một danh sách các DocTests được xác định bởi docstring của đối tượng hoặc bởi bất kỳ chuỗi docstring nào của đối tượng chứa nó.

DocTestParser Class

Nó là một lớp xử lý được sử dụng để trích xuất các ví dụ tương tác từ một chuỗi và sử dụng chúng để tạo một đối tượng DocTest. Lớp này định nghĩa các phương thức sau:

  • get_doctest() - Trích xuất tất cả các ví dụ về học thuyết từ chuỗi đã cho và thu thập chúng vào một DocTest vật.

  • get_examples(string[, name]) - Trích xuất tất cả các ví dụ về học thuyết từ chuỗi đã cho và trả lại chúng dưới dạng danh sách Examplecác đối tượng. Số dòng dựa trên 0. Tên đối số tùy chọn là tên xác định chuỗi này và chỉ được sử dụng cho các thông báo lỗi.

  • parse(string[, name]) - Chia chuỗi đã cho thành các ví dụ và văn bản xen kẽ, và trả lại chúng dưới dạng danh sách xen kẽ Examplesvà chuỗi. Số dòng choExamplesdựa trên 0. Tên đối số tùy chọn là tên xác định chuỗi này và chỉ được sử dụng cho các thông báo lỗi.

Lớp DocTestRunner

Đây là một lớp xử lý được sử dụng để thực thi và xác minh các ví dụ tương tác trong DocTest. Các phương thức sau được định nghĩa trong đó:

report_start ()

Báo cáo rằng người chạy thử sắp xử lý ví dụ đã cho. Phương thức này được cung cấp để cho phép các lớp con củaDocTestRunnerđể tùy chỉnh đầu ra của họ; nó không nên được gọi trực tiếp

report_success ()

Báo cáo rằng ví dụ đã cho đã chạy thành công. Phương pháp này được cung cấp để cho phép các lớp con của DocTestRunner tùy chỉnh đầu ra của chúng; nó không nên được gọi trực tiếp.

report_failure ()

Báo cáo rằng ví dụ đã cho không thành công. Phương thức này được cung cấp để cho phép các lớp con củaDocTestRunnerđể tùy chỉnh đầu ra của họ; nó không nên được gọi trực tiếp.

report_uneosystem_exception ()

Báo cáo rằng ví dụ đã cho nêu ra một ngoại lệ không mong muốn. Phương pháp này được cung cấp để cho phép các lớp con của DocTestRunner tùy chỉnh đầu ra của chúng; nó không nên được gọi trực tiếp.

chạy (thử nghiệm)

Chạy các ví dụ trong bài kiểm tra (một đối tượng doctest), và hiển thị kết quả bằng cách sử dụng chức năng nhà văn ra .

tóm tắt ([verbose])

In bản tóm tắt của tất cả các trường hợp thử nghiệm đã được chạy bởi DocTestRunner này và trả về một bộ TestResults có tên (không thành công, đã thử). Đối số dài dòng tùy chọn kiểm soát mức độ chi tiết của bản tóm tắt. Nếu độ dài không được chỉ định, thì độ dài của DocTestRunner sẽ được sử dụng.

Lớp OutputChecker

Lớp này được sử dụng để kiểm tra xem đầu ra thực tế từ một ví dụ học thuyết có khớp với đầu ra mong đợi hay không.

Các phương thức sau được định nghĩa trong lớp này:

check_output ()

Trở về Truenếu đầu ra thực tế từ một ví dụ ( got ) khớp với đầu ra dự kiến ​​( muốn ). Các chuỗi này luôn được coi là khớp nếu chúng giống hệt nhau; nhưng tùy thuộc vào cờ tùy chọn mà người chạy thử nghiệm đang sử dụng, một số loại đối sánh không chính xác cũng có thể xảy ra. Xem phần Cờ tùy chọnChỉ thị để biết thêm thông tin về cờ tùy chọn.

output_difference ()

Trả về một chuỗi mô tả sự khác biệt giữa đầu ra mong đợi cho một ví dụ nhất định ( ví dụ ) và đầu ra thực tế ( nhận ).

Tích hợp DocTest với Unittest

Mô-đun học thuyết cung cấp hai chức năng có thể được sử dụng để tạo các bộ thử nghiệm mới nhất từ ​​các mô-đun và tệp văn bản chứa học thuyết. Để tích hợp với khám phá thử nghiệm mới nhất, hãy bao gồm hàm load_tests () trong mô-đun thử nghiệm của bạn -

import unittest
import doctest
import doctestexample

def load_tests(loader, tests, ignore):
   tests.addTests(doctest.DocTestSuite(doctestexample))
   return tests

Một trang web TestSuite tổng hợp của các bài kiểm tra từ học thuyết cũng như đơn nhất sẽ được hình thành và hiện nó có thể được thực thi bằng phương thức main () hoặc phương thức run () của mô-đun đơn nhất.

Sau đây là hai chức năng chính để tạo unittest.TestSuite các phiên bản từ tệp văn bản và mô-đun với các học thuyết -

doctest.DocFileSuite ()

Nó được sử dụng để chuyển đổi các bài kiểm tra học thuyết từ một hoặc nhiều tệp văn bản thành unittest.TestSuite. Unittest.TestSuite được trả về sẽ được chạy bởi framework duy nhất và chạy các ví dụ tương tác trong mỗi tệp. Nếu bất kỳ ví dụ nào trong tệp không thành công, thì kiểm tra đơn vị tổng hợp không thành công vàfailureException ngoại lệ được nêu ra hiển thị tên của tệp chứa thử nghiệm và số dòng (đôi khi gần đúng).

doctest.DocTestSuite ()

Nó được sử dụng để chuyển đổi các bài kiểm tra học thuyết cho một mô-đun thành unittest.TestSuite.

Unittest.TestSuite được trả về phải được chạy bởi framework duy nhất và chạy từng học thuyết trong mô-đun. Nếu bất kỳ học thuyết nào không thành công, thì bài kiểm tra đơn vị tổng hợp không thành công vàfailureException ngoại lệ được nêu ra hiển thị tên của tệp chứa bài kiểm tra và số dòng (đôi khi gần đúng)

Dưới vỏ bọc, DocTestSuite () tạo unittest.TestSuite ngoài các phiên bản của doctest.DocTestCase và DocTestCase là lớp con của Unittest.TestCase.

Tương tự như vậy, DocFileSuite () tạo ra một.TestSuite đơn nhất ngoài các thể hiện của doctest.DocFileCase và DocFileCase là một lớp con của DocTestCase.

Vì vậy, cả hai cách để tạo một phiên bản DocTestSuite chạy nhất của DocTestCase. Khi bạn tự chạy các chức năng học thuyết, bạn có thể kiểm soát trực tiếp các tùy chọn học thuyết đang sử dụng bằng cách chuyển cờ tùy chọn cho các chức năng học thuyết.

Tuy nhiên, nếu bạn đang viết một khung công tác đơn nhất, thì cuối cùng, khung công tác mới nhất sẽ kiểm soát thời gian và cách thức chạy các bài kiểm tra. Tác giả khung thường muốn kiểm soát các tùy chọn báo cáo học thuyết (có lẽ, ví dụ: được chỉ định bởi các tùy chọn dòng lệnh), nhưng không có cách nào để chuyển các tùy chọn thông qua trình chạy thử nghiệm học thuyết duy nhất.

Vào năm 2004, Holger Krekel đã đổi tên stdgói, có tên thường bị nhầm lẫn với tên của Thư viện chuẩn được vận chuyển bằng Python, với tên (chỉ hơi khó hiểu hơn một chút) 'py.' Mặc dù gói chứa một số gói con, nhưng giờ đây nó được biết đến gần như hoàn toàn nhờ khung công tác py.test.

Khung công tác py.test đã thiết lập một tiêu chuẩn mới cho thử nghiệm Python và ngày nay đã trở nên rất phổ biến với nhiều nhà phát triển. Các thành ngữ thanh lịch và Pythonic mà nó giới thiệu cho bài viết kiểm tra đã giúp các bộ đề kiểm tra có thể được viết theo một phong cách nhỏ gọn hơn nhiều.

py.test là một giải pháp thay thế không có bảng soạn sẵn cho mô-đun đơn nhất tiêu chuẩn của Python. Mặc dù là một công cụ kiểm tra có đầy đủ tính năng và có thể mở rộng, nó tự hào về một cú pháp đơn giản. Tạo một bộ thử nghiệm dễ dàng như viết một mô-đun với một vài chức năng.

py.test chạy trên tất cả các hệ điều hành POSIX và WINDOWS (XP / 7/8) với phiên bản Python 2.6 trở lên.

Cài đặt

Sử dụng mã sau để tải mô-đun pytest trong bản phân phối Python hiện tại cũng như tiện ích py.test.exe. Có thể chạy thử nghiệm bằng cả hai.

pip install pytest

Sử dụng

Bạn có thể chỉ cần sử dụng câu lệnh khẳng định để xác nhận các kỳ vọng thử nghiệm. Sự xem xét nội tâm khẳng định của pytest sẽ báo cáo một cách thông minh các giá trị trung gian của biểu thức khẳng định, giải phóng bạn khỏi nhu cầu tìm hiểu nhiều tên củaJUnit legacy methods.

# content of test_sample.py
def func(x):
   return x + 1
   
def test_answer():
   assert func(3) == 5

Sử dụng dòng lệnh sau để chạy thử nghiệm trên. Sau khi chạy thử nghiệm, kết quả sau được hiển thị trên bảng điều khiển:

C:\Python27>scripts\py.test -v test_sample.py
============================= test session starts =====================
platform win32 -- Python 2.7.9, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- C:\Pyth
on27\python.exe
cachedir: .cache
rootdir: C:\Python27, inifile:
collected 1 items
test_sample.py::test_answer FAILED
================================== FAILURES =====================
_________________________________ test_answer _________________________________
   def test_answer():
>  assert func(3) == 5
E     assert 4 == 5
E     + where 4 = func(3)
test_sample.py:7: AssertionError
========================== 1 failed in 0.05 seconds ====================

Thử nghiệm cũng có thể được chạy từ dòng lệnh bằng cách bao gồm mô-đun pytest sử dụng công tắc –m.

python -m pytest test_sample.py

Nhóm nhiều bài kiểm tra trong một lớp

Một khi bạn bắt đầu có nhiều hơn một vài bài kiểm tra, việc nhóm các bài kiểm tra một cách hợp lý, trong các lớp và mô-đun thường có ý nghĩa. Hãy viết một lớp chứa hai bài kiểm tra -

class TestClass:
   def test_one(self):
      x = "this"
      assert 'h' in x
   def test_two(self):
      x = "hello"
      assert hasattr(x, 'check')

Kết quả kiểm tra sau sẽ được hiển thị:

C:\Python27>scripts\py.test -v test_class.py
============================= test session starts =====================
platform win32 -- Python 2.7.9, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- C:\Pyt
on27\python.exe
cachedir: .cache
rootdir: C:\Python27, inifile:
collected 2 items
test_class.py::TestClass::test_one PASSED
test_class.py::TestClass::test_two FAILED
================================== FAILURES =====================
_____________________________ TestClass.test_two ______________________________
self = <test_class.TestClass instance at 0x01309DA0>

   def test_two(self):
      x = "hello"
>  assert hasattr(x, 'check')
E     assert hasattr('hello', 'check')

test_class.py:7: AssertionError
===================== 1 failed, 1 passed in 0.06 seconds ======================

Dự án mũi được phát hành vào năm 2005, một năm sau đó py.testđã nhận được chiêu bài hiện đại của nó. Nó được viết bởi Jason Pellerin để hỗ trợ cùng một thành ngữ thử nghiệm đã được py.test tiên phong, nhưng trong một gói dễ cài đặt và bảo trì hơn.

Các nose mô-đun có thể được cài đặt với sự trợ giúp của tiện ích pip

pip install nose

Thao tác này sẽ cài đặt mô-đun mũi trong bản phân phối Python hiện tại cũng như nosetest.exe, có nghĩa là có thể chạy thử nghiệm bằng tiện ích này cũng như sử dụng công tắc –m.

C:\python>nosetests –v test_sample.py
Or
C:\python>python –m nose test_sample.py

nose thu thập các bài kiểm tra từ unittest.TestCasetất nhiên là các lớp con. Chúng ta cũng có thể viết các hàm kiểm tra đơn giản, cũng như các lớp kiểm tra không phải là lớp con của unittest.TestCase. Mũi cũng cung cấp một số chức năng hữu ích để viết các bài kiểm tra theo thời gian, kiểm tra các trường hợp ngoại lệ và các trường hợp sử dụng phổ biến khác.

nosethu thập các bài kiểm tra tự động. Không cần phải thu thập thủ công các trường hợp thử nghiệm vào các bộ thử nghiệm. Chạy thử nghiệm là đáp ứng, vìnose bắt đầu chạy thử nghiệm ngay sau khi mô-đun thử nghiệm đầu tiên được tải.

Như với mô-đun đơn nhất, nose hỗ trợ các thiết bị cố định ở cấp độ gói, mô-đun, lớp và trường hợp thử nghiệm, vì vậy việc khởi tạo tốn kém có thể được thực hiện không thường xuyên.

Cách sử dụng cơ bản

Hãy để chúng tôi xem xét nosetest.py tương tự như tập lệnh được sử dụng trước đó -

# content of nosetest.py
def func(x):
   return x + 1
   
def test_answer():
   assert func(3) == 5

Để chạy thử nghiệm trên, hãy sử dụng cú pháp dòng lệnh sau:

C:\python>nosetests –v nosetest.py

Kết quả hiển thị trên bảng điều khiển sẽ như sau:

nosetest.test_answer ... FAIL
================================================================
FAIL: nosetest.test_answer
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python34\lib\site-packages\nose\case.py", line 198, in runTest
      self.test(*self.arg)
   File "C:\Python34\nosetest.py", line 6, in test_answer
      assert func(3) == 5
AssertionError
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures = 1)

nose có thể được tích hợp với DocTest bằng cách sử dụng with-doctest tùy chọn trong dòng lệnh Athe bove.

\nosetests --with-doctest -v nosetest.py

Bạn có thể sử dụng nose trong một kịch bản thử nghiệm -

import nose
nose.main()

Nếu bạn không muốn tập lệnh thử nghiệm thoát với 0 khi thành công và 1 khi thất bại (như unittest.main), hãy sử dụng mũi.run () để thay thế -

import nose
result = nose.run()

Kết quả sẽ là true nếu chạy thử thành công, hoặc false nếu không thành công hoặc tạo ra một ngoại lệ không cần thiết.

nosehỗ trợ đồ đạc (phương pháp thiết lập và xé nhỏ) ở cấp độ gói, mô-đun, lớp và thử nghiệm. Như với py.test hoặc đồ đạc đơn nhất, thiết lập luôn chạy trước bất kỳ thử nghiệm nào (hoặc tập hợp các thử nghiệm cho các gói và mô-đun thử nghiệm); teardown chạy nếu thiết lập đã hoàn tất thành công, bất kể trạng thái của quá trình chạy thử nghiệm.

Mô-đun arrow.tools cung cấp một số công cụ hỗ trợ kiểm tra mà bạn có thể thấy hữu ích, bao gồm các trình trang trí để hạn chế thời gian thực hiện kiểm tra và kiểm tra các ngoại lệ, và tất cả các phương pháp khẳng định tương tự được tìm thấy trong unittest.TestCase.

  • nose.tools.ok_(expr, msg = None) - Viết tắt để khẳng định.

  • nose.tools.eq_(a, b, msg = None) - Viết tắt cho 'khẳng định a == b, “% r! =% R”% (a, b)

  • nose.tools.make_decorator(func) - Bao bọc một trình trang trí thử nghiệm để sao chép chính xác siêu dữ liệu của chức năng được trang trí, bao gồm cả nội dung bổ sung của mũi (cụ thể là thiết lập và xé nhỏ).

  • nose.tools.raises(*exceptions) - Kiểm tra phải nêu ra một trong các ngoại lệ dự kiến ​​để vượt qua.

  • nose.tools.timed(limit) - Bài kiểm tra phải kết thúc trong thời hạn quy định để vượt qua

  • nose.tools.istest(func) - Người trang trí để đánh dấu một chức năng hoặc phương pháp như một bài kiểm tra

  • nose.tools.nottest(func) - Người trang trí để đánh dấu một hàm hoặc phương pháp không phải là một bài kiểm tra

Kiểm tra tham số hóa

Khung thử nghiệm của Python, mới nhất, không có cách đơn giản để chạy các trường hợp thử nghiệm được tham số hóa. Nói cách khác, bạn không thể dễ dàng chuyển các đối số thànhunittest.TestCase từ bên ngoài.

Tuy nhiên, các cổng mô-đun pytest kiểm tra tham số hóa theo một số cách được tích hợp tốt -

  • pytest.fixture() cho phép bạn xác định tham số hóa ở cấp độ các hàm cố định.

  • @pytest.mark.parametrizecho phép xác định tham số hóa ở cấp độ hàm hoặc lớp. Nó cung cấp nhiều bộ đối số / cố định cho một hàm hoặc lớp kiểm tra cụ thể.

  • pytest_generate_tests cho phép triển khai lược đồ hoặc tiện ích mở rộng tham số động tùy chỉnh của riêng bạn.

Mô-đun bên thứ ba 'mũi tham số' cho phép thử nghiệm Tham số hóa với bất kỳ khung thử nghiệm Python nào. Nó có thể được tải xuống từ liên kết này -https://github.com/wolever/nose-parameterized