python에서 자주 사용하는 단원 테스트 프레임워크 유니버설

1. unitest 주요 기능 모듈 소개


unitest는 주로 Test Case, Test Suite, Test Loader, Text Test Runner, Text Test Result 등 몇 가지 기능 모듈을 포함한다.
  • Test Case: 하나의 Test Case 실례는 하나의 테스트 용례이고 하나의 테스트 용례는 완전한 테스트 절차이다. 테스트 전 환경의 구축, 테스트 코드의 집행, 테스트 후 환경의 복원 또는 폐기를 포함한다.원 테스트의 본질도 바로 여기에 있다. 하나의 테스트 용례는 완전한 테스트 단원으로 특정한 구체적인 문제에 대해 검사 검증을 할 수 있다
  • Test Suite: 여러 테스트 용례를 한데 모으면 Test Suite입니다. Test Suite도 Test Suite를 끼워 넣을 수 있습니다..
  • TestLoader: TestLoader의 역할은 Testcase를 TestSuite에 로드하는 것입니다..
  • TextTestRunner: TextTestRunner는 테스트 용례를 실행하는 데 사용되며, 그 중 run(test)은 TestSuite/TestCase의 run(result) 방법을 실행합니다..
  • TextTestResult: TextTestResult는 테스트 결과를 저장하는 데 사용됩니다. 테스트 용례가 얼마나 실행되었는지, 얼마나 성공했는지, 얼마나 실패했는지 등 정보를 포함합니다..
  • 전체 절차는 TestCase를 작성한 다음 TestLoader에서 TestCase를 TestSuite로 불러오고 TextTestRunner에서 TestSuite를 실행하며 실행 결과는 TextTestResult에 저장됩니다.

    2. 실례 소개


    우선 몇 가지 측정할 방법을 준비하여test_func.py 중.
    
    def add(a, b):
      return a + b
    
    
    def multi(a, b):
      return a * b
    
    
    def lower_str(string):
      return string.lower()
    
    
    def square(x):
      return x ** 2
    몇 가지 테스트를 기다리는 방법을 준비한 후, 이 방법들을 위해 테스트 용례를 쓰고our_testcase.py 중.
    
    import unittest
    from test_func import *
    
    
    class TestFunc(unittest.TestCase):
      """Test test_func.py"""
    
      def test_add(self):
        """Test func add"""
        self.assertEqual(3, add(1, 2))
        self.assertNotEqual(3, add(1, 3))
    
      def test_multi(self):
        """Test func multi"""
        self.assertEqual(6, multi(2, 3))
        self.assertNotEqual(8, multi(3, 3))
    
      def test_lower_str(self):
        """Test func lower_str"""
        self.assertEqual("abc", lower_str("ABC"))
        self.assertNotEqual("Dce", lower_str("DCE"))
    
      def test_square(self):
        """Test func square"""
        self.assertEqual(17, square(4)) #  , 4 17, 。
        self.assertNotEqual(35, square(6))
    
    
    if __name__ == '__main__':
      unittest.main()
    여기 다 쓰고 명령행 단말기에 들어가서python our_testcase.py, 실행 결과는 다음과 같습니다.
    
    ...F
    ======================================================================
    FAIL: test_square (__main__.TestFunc)
    Test func square
    ----------------------------------------------------------------------
    Traceback (most recent call last):
     File "our_testcase.py", line 27, in test_square
      self.assertEqual(17, square(4))
    AssertionError: 17 != 16
    
    ----------------------------------------------------------------------
    Ran 4 tests in 0.000s
    
    FAILED (failures=1)
    여기서 이 집행 결과를 분석해 봅시다.먼저 총 4개의 테스트 용례가 실행되었고 1개가 실패했으며 실패 원인을 알 수 있습니다. AssertionError: 17!=16, 이것은 우리가 고의로 남긴 잘못된 구멍으로 테스트 용례에 의해 테스트되었다.
    첫 줄...F, 점 하나.대표 테스트 성공, F 대표 실패, 우리의 테스트 결과 중 세 번째 성공, 네 번째 실패, 총 네 개의 테스트, 나머지 기호 중 E 대표 오류, S 대표 건너뛰기.
    특히 설명하는 점은 테스트의 집행 순서는 방법의 순서와 관계가 없고 네 가지 테스트는 무작위로 선후로 집행된다는 것이다.
    모든 테스트 방법을 작성할 때test로 시작해야 합니다. 예를 들어test_square, 그렇지 않으면 unitest에 식별되지 않습니다.
    유니테스트에서main () 에verbosity 파라미터를 추가하면 출력의 오류 보고서를 제어할 수 있는 상세한 프로그램입니다. 기본값은 1입니다. 0으로 설정하면 모든 용례의 실행 결과, 즉 위의 첫 줄의 실행 결과 내용을 출력하지 않습니다.2로 설정하면 세부 실행 결과가 출력됩니다.
    수정our_testcase.py의 주 함수입니다.
    
    if __name__ == '__main__':
      unittest.main(verbosity=2)
    실행 결과는 다음과 같다.
    
    test_add (__main__.TestFunc)
    Test func add ... ok
    test_lower_str (__main__.TestFunc)
    Test func lower_str ... ok
    test_multi (__main__.TestFunc)
    Test func multi ... ok
    test_square (__main__.TestFunc)
    Test func square ... FAIL
    
    ======================================================================
    FAIL: test_square (__main__.TestFunc)
    Test func square
    ----------------------------------------------------------------------
    Traceback (most recent call last):
     File "our_testcase.py", line 27, in test_square
      self.assertEqual(17, square(4))
    AssertionError: 17 != 16
    
    ----------------------------------------------------------------------
    Ran 4 tests in 0.000s
    
    FAILED (failures=1)
    각 용례의 상세한 실행 상황과 용례 이름, 용례 설명이 모두 출력되었음을 알 수 있습니다. 테스트 방법에 코드 예시 중의 "Doc String"을 추가하면 용례가 실행될 때 이 문자열을 이 용례의 설명으로 하고 적당한 주석을 추가하면 출력된 테스트 보고서를 더욱 쉽게 읽을 수 있습니다.

    3. TestSuite 구성


    위의 테스트 방법에 따라 우리는 용례 집행의 순서를 통제할 수 없다. 이것은 분명히 불합리한 것이다. 왜냐하면 일부 테스트 과정에서 우리는 반드시 먼저 어떤 용례를 테스트하고 다시 어떤 용례를 테스트해야 하기 때문이다. 이런 용례는 선후의 인과 관계가 있기 때문이다.여기에서 TestSuite가 필요합니다.Test Suite에 추가된 케이스는 추가된 순서대로 실행됩니다.
    또 하나의 문제는 우리가 현재 테스트 파일이 하나밖에 없기 때문에 이 파일을 직접 실행하면 되지만 여러 개의 테스트 파일이 있다면 어떻게 조직할 것인가 하는 것이다. 파일 하나하나를 실행할 수 없겠지. 답도 Test Suite에 있다.
    새 파일,test_suite.py.
    
    import unittest
    from our_testcase import TestFunc
    
    if __name__ == '__main__':
      suite = unittest.TestSuite()
      tests = [TestFunc("test_square"), TestFunc("test_lower_str"), TestFunc("test_multi")]
      suite.addTests(tests)
      runner = unittest.TextTestRunner(verbosity=2)
      runner.run(suite)
    실행 결과는 다음과 같다.
    
    test_square (our_testcase.TestFunc)
    Test func square ... FAIL
    test_lower_str (our_testcase.TestFunc)
    Test func lower_str ... ok
    test_multi (our_testcase.TestFunc)
    Test func multi ... ok
    
    ======================================================================
    FAIL: test_square (our_testcase.TestFunc)
    Test func square
    ----------------------------------------------------------------------
    Traceback (most recent call last):
     File "/Users/luyuze/projects/test/our_testcase.py", line 27, in test_square
      self.assertEqual(17, square(4))
    AssertionError: 17 != 16
    
    ----------------------------------------------------------------------
    Ran 3 tests in 0.000s
    
    FAILED (failures=1)
    이렇게 하면 예를 들어 집행하는 순서는 우리가 추가한 순서에 따라 집행하는 것이다.
    Test Suite의 add Tests () 방법을 사용하고 Test Case 목록에 직접 전송합니다. 다른 방법도 Test Suite에 용례를 추가할 수 있습니다.
    
    #  addTest TestCase
    suite.addTest(TestMathFunc("test_multi"))
    
    
    #  loadTestFromName, .TestCase , 
    suite.addTests(unittest.TestLoader().loadTestsFromName('our_testcase.TestFunc'))
    suite.addTests(unittest.TestLoader().loadTestsFromNames(['our_testcase.TestFunc']))
    
    
    # loadTestsFromTestCase(), TestCase
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestFunc))
    TestLoader의 방법으로는 케이스를 정렬할 수 없으며, suite에서도 suite를 정렬할 수 있습니다.

    4. 파일 내보내기


    예를 들어 조직되었지만 결과는 컨트롤러로만 출력할 수 있습니다. 이렇게 하면 이전의 실행 기록을 볼 수 없습니다. 우리는 결과를 파일로 출력하려고 합니다.
    수정 test_suite.py.
    
    import unittest
    from our_testcase import TestFunc
    
    if __name__ == '__main__':
      suite = unittest.TestSuite()
      tests = [TestFunc("test_square"), TestFunc("test_lower_str"), TestFunc("test_multi")]
      suite.addTests(tests)
    
      with open('UnitestTextReport.txt', 'a') as f:
        runner = unittest.TextTestRunner(stream=f, verbosity=2)
        runner.run(suite)

    5. 테스트 전후의 처리


    이전의 테스트에서 이런 문제가 존재할 수 있다. 만약에 테스트 전에 환경을 준비하고 테스트가 끝난 후에 정리를 하려면 어떻게 해야 합니까?여기에 필요한 것은 set Up () 과 tear Down () 입니다.
    수정our_testcase.py.
    
    import unittest
    from test_func import *
    
    
    class TestFunc(unittest.TestCase):
      """Test test_func.py"""
      
      def setUp(self):
        print("do something before testcase")
    
      def test_add(self):
        """Test func add"""
        self.assertEqual(3, add(1, 2))
        self.assertNotEqual(3, add(1, 3))
    
      def test_multi(self):
        """Test func multi"""
        self.assertEqual(6, multi(2, 3))
        self.assertNotEqual(8, multi(3, 3))
    
      def test_lower_str(self):
        """Test func lower_str"""
        self.assertEqual("abc", lower_str("ABC"))
        self.assertNotEqual("Dce", lower_str("DCE"))
    
      def test_square(self):
        """Test func square"""
        self.assertEqual(17, square(4))
        self.assertNotEqual(35, square(6))
        
      def tearDownClass(self):
        print("do something after testcase")
    
    
    if __name__ == '__main__':
      unittest.main(verbosity=2)
    
    실행 결과:
    
    test_add (__main__.TestFunc)
    Test func add ... do something before testcase
    do something after testcase
    ok
    test_lower_str (__main__.TestFunc)
    Test func lower_str ... do something before testcase
    do something after testcase
    ok
    test_multi (__main__.TestFunc)
    Test func multi ... do something before testcase
    do something after testcase
    ok
    test_square (__main__.TestFunc)
    Test func square ... do something before testcase
    do something after testcase
    FAIL
    
    ======================================================================
    FAIL: test_square (__main__.TestFunc)
    Test func square
    ----------------------------------------------------------------------
    Traceback (most recent call last):
     File "our_testcase.py", line 30, in test_square
      self.assertEqual(17, square(4))
    AssertionError: 17 != 16
    
    ----------------------------------------------------------------------
    Ran 4 tests in 0.001s
    
    FAILED (failures=1)
    setUp () 과 TearDown () 이 각각의 케이스 전후에 한 번씩 실행된 것을 발견할 수 있습니다.모든 케이스가 실행되기 전과 모든 케이스가 실행된 후에 환경을 준비하고 정리하려면 setUpClass () 와tearDownClass () 를 사용할 수 있습니다.
    
    class TestFunc(unittest.TestCase):
      """Test test_func.py"""
    
      @classmethod
      def setUpClass(cls):
        print "This setUpClass() method only called once."
    
      @classmethod
      def tearDownClass(cls):
        print "This tearDownClass() method only called once too."

    6. 케이스 건너뛰기


    만약 우리가 임시로 어떤 케이스를 건너뛰고 실행하지 않으려면, 유니버설도 상응하는 방법이 있다.
    1. skip 장식기
    
    # -*- coding: utf-8 -*-
    
    import unittest
    from test_func import *
    
    
    class TestFunc(unittest.TestCase):
      """Test test_func.py"""
    
      @unittest.skip('do not run this case')
      def test_add(self):
        """Test func add"""
        self.assertEqual(3, add(1, 2))
        self.assertNotEqual(3, add(1, 3))
    
      def test_multi(self):
        """Test func multi"""
        self.assertEqual(6, multi(2, 3))
        self.assertNotEqual(8, multi(3, 3))
    
      def test_lower_str(self):
        """Test func lower_str"""
        self.assertEqual("abc", lower_str("ABC"))
        self.assertNotEqual("Dce", lower_str("DCE"))
    
      def test_square(self):
        """Test func square"""
        self.assertEqual(17, square(4))
        self.assertNotEqual(35, square(6))
    
    
    if __name__ == '__main__':
      unittest.main(verbosity=2)
    실행 결과:
    
    test_add (__main__.TestFunc)
    Test func add ... skipped 'do not run this case'
    test_lower_str (__main__.TestFunc)
    Test func lower_str ... ok
    test_multi (__main__.TestFunc)
    Test func multi ... ok
    test_square (__main__.TestFunc)
    Test func square ... FAIL
    
    ======================================================================
    FAIL: test_square (__main__.TestFunc)
    Test func square
    ----------------------------------------------------------------------
    Traceback (most recent call last):
     File "our_testcase.py", line 28, in test_square
      self.assertEqual(17, square(4))
    AssertionError: 17 != 16
    
    ----------------------------------------------------------------------
    Ran 4 tests in 0.000s
    
    FAILED (failures=1, skipped=1)
    그 결과 총 4개의 테스트를 실행했고 1개는 실패했으며 1개는 건너뛰었다.
    skip 장식기는 모두 세 개의 유닛이 있습니다.skip(reason)、unittest.skipIf(condition, reason)、unittest.skipUnless(condition,reason),skip는 무조건 건너뛰고,skipIf는condition이 True일 때 건너뛰고,skipUnless는condition이 False일 때 건너뛴다.
    2、TestCase.skipTest() 메서드
    
    class TestFunc(unittest.TestCase):
      """Test test_func.py"""
    
      def test_add(self):
        """Test func add"""
        self.skipTest("do not run this case")
        self.assertEqual(3, add(1, 2))
        self.assertNotEqual(3, add(1, 3))
    효과는 첫 번째와 같다.
    이상은python에서 자주 사용하는 단원 테스트 프레임워크 unitest의 상세한 내용을 전면적으로 소개하고,python 단원 테스트 프레임워크 unitest에 대한 더 많은 자료는 저희 다른 관련 글에 주목하세요!

    좋은 웹페이지 즐겨찾기