# 7/22共筆 {%hackmd 1lpg7PuqRoaui6XyJcrylw %} ## Handel Test Fail ```flow execute_test=>start: 執行測試 pass=>end: 結束 fail=>end: 測試失敗 execute_step=>operation: 執行測試步驟 teardown=>operation: Teardown is_step_pass=>condition: 步驟成功? is_last_step=>condition: 還有步驟? execute_test->execute_step->is_step_pass is_step_pass(yes)->is_last_step is_step_pass(no)->fail is_last_step(yes)->execute_step is_last_step(no)->pass ``` ### behave(Cucumber) - 用`feature`, `scenario`, `step`獲取狀態 - `feature.status` [^feature.status] - `untested` The feature was has not been completely tested yet. - `skipped` One or more steps of this feature was passed over during testing. - `passed` The feature was tested successfully. - `failed` One or more steps of this feature failed. - `scenario.status`[^scenario.status] - `untested` The scenario was has not been completely tested yet. - `skipped` One or more steps of this scenario was passed over during testing. - `passed` The scenario was tested successfully. - `failed` One or more steps of this scenario failed. - `step.status` [^step.status] - `untested` This step was not run (yet). - `skipped` This step was skipped during testing. - `passed` The step was tested successfully. - `failed` The step failed. - `undefined` The step has no matching step implementation. [^feature.status]: [feature.status](https://behave.readthedocs.io/en/stable/api.html?highlight=.status#behave.model.Feature.status) [^scenario.status]: [scenario.status](https://behave.readthedocs.io/en/stable/api.html?highlight=.status#behave.model.Scenario.status) [^step.status]: [step.status](https://behave.readthedocs.io/en/stable/api.html?highlight=.status#behave.model.Step.status) - **其中一種常用的作法**是配合`envirnment.py`的Environmental Controls Function - `after_step(context, step)` - `after_scenario(context, scenario)` - `after_feature(context, feature)` - 或是配合自定義的argument和`pdb`[^pdb](Python build-in的Debugger) [^pdb]: [The_Python_Debugger](https://docs.python.org/3/library/pdb.html) - 範例 ```python # envirnmnet.py def debug_on_error(userdata): """ Turn the debug on error on/off. Use the "behave" command to inpust the value. behave --no-capture -D DEBUG_ON_ERROR (to enable debug-on-error) behave --no-capture -D DEBUG_ON_ERROR=yes (to enable debug-on-error) ehave --no-capture -D DEBUG_ON_ERROR=no (to disable debug-on-error) """ global DEBUG_ON_ERROR DEBUG_ON_ERROR = userdata.getbool("DEBUG_ON_ERROR") def before_all(context): debug_on_error(context.config.userdata) def after_step(context, step): if DEBUG_ON_ERROR and step.status == "failed": import pdb pdb.post_mortem(step.exc_traceback) ``` ### Robot Framework - Test and suite statuses `PASS`, `FAIL` or `SKIP` - 用Build-in Keyword寫在`.robot`[^continue_on_failure] - `Run Keyword And Ignore Error and Run Keyword And Expect Error keywords` - `Run Keyword And Warn On Failure` - `Special failures from keywords` - `Run Keyword And Continue On Failure keyword` - 用`robot:continue-on-failure`的tags[^controlling-continue-on-failure-using-reserved-tags] ``` *** Test Cases *** Test 1 Run Keyword and Continue on Failure Should be Equal 1 2 User Keyword 1 Test 2 [Tags] robot:continue-on-failure Should be Equal 1 2 User Keyword 2 *** Keywords *** User Keyword 1 Run Keyword and Continue on Failure Should be Equal 3 4 Log this message is logged User Keyword 2 [Tags] robot:continue-on-failure Should be Equal 3 4 Log this message is logged ``` [^continue_on_failure]: [Continue_on_failure](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#continue-on-failure) [^controlling-continue-on-failure-using-reserved-tags]: [controlling-continue-on-failure-using-reserved-tags](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#controlling-continue-on-failure-using-reserved-tags) - 寫在`Implement Code`,用robot API - `robot.api` - `robot.result` - `robot.running` ```python= import sys from robot.api import ExecutionResult, ResultVisitor class ExecutionTimeChecker(ResultVisitor): def __init__(self, max_seconds): self.max_milliseconds = max_seconds * 1000 def visit_test(self, test): if test.status == 'PASS' and test.elapsedtime > self.max_milliseconds: test.status = 'FAIL' test.message = 'Test execution took too long.' ``` --- ## 補充 ![](https://i.imgur.com/eXmei6n.png)