# 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.'
```
---
## 補充
