1. 程式人生 > >Pyunit原始碼筆記之七 testcase正式執行,重點重點重點

Pyunit原始碼筆記之七 testcase正式執行,重點重點重點

接上文,執行測試用例中的setup等等:

self.setUp()要先執行,執行無異常後,再執行testMethod()和self.tearDown()

try:
            self._outcome = outcome

            with outcome.testPartExecutor(self):
                self.setUp()
            if outcome.success:
                outcome.expecting_failure = expecting_failure
                with outcome.testPartExecutor(self, isTest=True):
                    testMethod()
                outcome.expecting_failure = False
                with outcome.testPartExecutor(self):
                    self.tearDown()

在上下文管理器outcome.testPartExecutor中:以yield為分界。

這裡的異常SkipTest,是指在執行過程中有raise SkipTest,

_ShouldStop也可以用在測試用例中,raise  except as _ShouldStop,

如果測試方法中有expecting_failure,失敗了也算success,帶出sys.exc_info()用self.expectedFailure = exc_info

如果其他原因fail的case,用self.errors.append((test_case, exc_info))記錄,同時帶出sys.exc_info()資訊。

self.success的值邏輯很重要。

這一部分是執行的測試用例的核心,個人覺得,很重要,很重要,很重要!

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, isTest=False):
        old_success = self.success
        self.success = True
        try:
            yield
        except KeyboardInterrupt:
            raise
        except SkipTest as e:
            self.success = False
            self.skipped.append((test_case, str(e)))
        except _ShouldStop:
            pass
        except:
            exc_info = sys.exc_info()
            if self.expecting_failure:
                self.expectedFailure = exc_info
            else:
                self.success = False
                self.errors.append((test_case, exc_info))
            # explicitly break a reference cycle:
            # exc_info -> frame -> exc_info
            exc_info = None
        else:
            if self.result_supports_subtests and self.success:
                self.errors.append((test_case, None))
        finally:
            self.success = self.success and old_success