Skip to content

Commit 1b58cc4

Browse files
authored
Merge pull request #15 from zhaowcheng/develop
v0.4.0
2 parents 05c603a + c26a8f7 commit 1b58cc4

38 files changed

+897
-774
lines changed

MANIFEST.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
recursive-include xbot/framework/statics *
22
include requirements.txt
3-
include README.zh.rst
3+
include README*

README.md

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
<p align="center">
2+
<br>English | <a href="README.zh.md">中文</a>
3+
</p>
4+
5+
***
6+
7+
## Introduction
8+
9+
xbot is a `lightweight`, `easy-to-use`, and `extensible` test automation framework.
10+
11+
## Installation
12+
13+
Install xbot via pip:
14+
15+
```
16+
pip install xbot.framework
17+
```
18+
19+
Type `xbot --help` to check:
20+
21+
```
22+
$ xbot --help
23+
usage: xbot [-h] [-d DIRECTORY] [-b TESTBED] [-s TESTSET] [-f {verbose,brief}] [-v] {init,run}
24+
25+
positional arguments:
26+
{init,run}
27+
28+
optional arguments:
29+
-h, --help show this help message and exit
30+
-d DIRECTORY, --directory DIRECTORY
31+
directory to init (required by `init` command)
32+
-b TESTBED, --testbed TESTBED
33+
testbed filepath (required by `run` command)
34+
-s TESTSET, --testset TESTSET
35+
testset filepath (required by `run` command)
36+
-f {verbose,brief}, --outfmt {verbose,brief}
37+
output format (option for `run` command, options: verbose/brief, default: brief)
38+
-v, --version show program's version number and exit
39+
```
40+
41+
42+
## Getting Started
43+
44+
Initialize a test project:
45+
46+
```
47+
$ xbot init -d ./testproj
48+
Initialized ./testproj
49+
```
50+
51+
The test project directory structure:
52+
53+
```
54+
./testproj
55+
├── README.md
56+
├── lib # test libraries
57+
│ ├── __init__.py
58+
│ ├── testbed.py # testbed base
59+
│ └── testcase.py # testcase base
60+
├── requirements.txt
61+
├── testbeds # directory storing testbeds
62+
│ └── testbed_example.yml
63+
├── testcases # directory storing testcases
64+
│ ├── __init__.py
65+
│ └── examples
66+
│ ├── __init__.py
67+
│ ├── nonpass
68+
│ │ ├── __init__.py
69+
│ │ ├── tc_eg_nonpass_error_clsname.py
70+
│ │ ├── tc_eg_nonpass_error_syntax.py
71+
│ │ ├── tc_eg_nonpass_fail_setup_with_failfast_false.py
72+
│ │ ├── tc_eg_nonpass_fail_setup_with_failfast_true.py
73+
│ │ ├── tc_eg_nonpass_fail_step_with_failfast_false.py
74+
│ │ ├── tc_eg_nonpass_fail_step_with_failfast_true.py
75+
│ │ ├── tc_eg_nonpass_skip_excluded.py
76+
│ │ ├── tc_eg_nonpass_skip_not_included.py
77+
│ │ └── tc_eg_nonpass_timeout.py
78+
│ └── pass
79+
│ ├── __init__.py
80+
│ ├── tc_eg_pass_create_dirs_and_files.py
81+
│ └── tc_eg_pass_get_values_from_testbed.py
82+
└── testsets # directory storing testsets
83+
└── testset_example.yml
84+
```
85+
86+
Testbed example(`testbeds/testbed_example.yml`):
87+
88+
```yaml
89+
# Testbed is used to store the information about the test environment.
90+
# The information can be accessed by self.testbed.get() in the testcases.
91+
example:
92+
key1: value1
93+
key2:
94+
key2-1: value2-1
95+
key2-2: value2-2
96+
key3:
97+
- value3-1
98+
- value3-2
99+
- value3-3
100+
key4:
101+
- name: jack
102+
age: 20
103+
- name: tom
104+
age: 30
105+
```
106+
107+
Testset example(`testsets/testset_example.yml`):
108+
109+
```yaml
110+
# Testset is used to organize testcases to be executed.
111+
tags: # `exclude` has higher priority than `include`.
112+
include: # Include testcases with these tags.
113+
- tag1
114+
exclude: # Exclude testcases with these tags.
115+
- tag2
116+
paths:
117+
- testcases/examples/pass/tc_eg_pass_get_values_from_testbed.py
118+
- testcases/examples/pass/tc_eg_pass_create_dirs_and_files.py
119+
# Recursively include all testcases in the directory,
120+
# only match files with the prefix 'tc_' and suffix '.py'.
121+
- testcases/examples/nonpass/
122+
```
123+
124+
Run the testcases(must execute under the test project directory):
125+
126+
```
127+
$ xbot run -b testbeds/testbed_example.yml -s testsets/testset_example.yml
128+
(1/11) PASS 0:00:01 tc_eg_pass_get_values_from_testbed
129+
(2/11) PASS 0:00:01 tc_eg_pass_create_dirs_and_files
130+
(3/11) ERROR 0:00:00 tc_eg_nonpass_error_clsname
131+
(4/11) ERROR 0:00:00 tc_eg_nonpass_error_syntax
132+
(5/11) FAIL 0:00:01 tc_eg_nonpass_fail_setup_with_failfast_false
133+
(6/11) FAIL 0:00:01 tc_eg_nonpass_fail_setup_with_failfast_true
134+
(7/11) FAIL 0:00:01 tc_eg_nonpass_fail_step_with_failfast_false
135+
(8/11) FAIL 0:00:01 tc_eg_nonpass_fail_step_with_failfast_true
136+
(9/11) SKIP 0:00:00 tc_eg_nonpass_skip_excluded
137+
(10/11) SKIP 0:00:00 tc_eg_nonpass_skip_not_included
138+
(11/11) TIMEOUT 0:00:03 tc_eg_nonpass_timeout
139+
140+
report: /Users/wan/CodeProjects/xbot.framework/testproj/logs/testbed_example/2024-07-02_12-19-43/report.html
141+
```
142+
143+
Test report and logs will be generated in the `logs` subdirectory.
144+
145+
Example report:
146+
147+
![report_example](https://github.com/zhaowcheng/xbot.framework/blob/master/xbot/framework/statics/report_example.png?raw=True)
148+
149+
Example log:
150+
151+
![log_example](https://github.com/zhaowcheng/xbot.framework/blob/master/xbot/framework/statics/log_example.png?raw=True)
152+
153+
154+
## Testcase Development
155+
156+
Testcases are stored in the `testcases` subdirectory, below is a example(`testcases/examples/pass/tc_eg_pass_create_dirs_and_files.py`):
157+
158+
```python
159+
import os
160+
import tempfile
161+
import shutil
162+
163+
from xbot.framework.utils import assertx
164+
from lib.testcase import TestCase
165+
166+
167+
class tc_eg_pass_create_dirs_and_files(TestCase):
168+
"""
169+
Test creating directories and files.
170+
"""
171+
TIMEOUT = 60
172+
FAILFAST = True
173+
TAGS = ['tag1']
174+
175+
def setup(self):
176+
"""
177+
Prepare test environment.
178+
"""
179+
self.workdir = tempfile.mkdtemp()
180+
self.info('Created workdir: %s', self.workdir)
181+
182+
def step1(self):
183+
"""
184+
Create a subdirectory 'dir' under the temporary working directory and check if it is created successfully.
185+
"""
186+
self.dir1 = os.path.join(self.workdir, 'dir1')
187+
os.mkdir(self.dir1)
188+
assertx(os.path.exists(self.dir1), '==', True)
189+
190+
def step2(self):
191+
"""
192+
Create an empty file 'file1' under 'dir1' and check if it is created successfully.
193+
"""
194+
self.file1 = os.path.join(self.dir1, 'file1')
195+
open(self.file1, 'w').close()
196+
assertx(os.path.exists(self.file1), '==', True)
197+
198+
def step3(self):
199+
"""
200+
Write 'hello world' to 'file1' and check if it is written successfully.
201+
"""
202+
with open(self.file1, 'w') as f:
203+
f.write('hello world')
204+
with open(self.file1, 'r') as f:
205+
assertx(f.read(), '==', 'hello world')
206+
207+
def teardown(self):
208+
"""
209+
Clean up test environment.
210+
"""
211+
shutil.rmtree(self.workdir)
212+
self.info('Removed workdir: %s', self.workdir)
213+
self.sleep(1)
214+
```
215+
216+
- Testcase `MUST` inherit from the `TestCase` base class;
217+
- Testcase `MUST` implement the preset steps in the setup method, write pass if there are no specific steps;
218+
- Testcase `MUST` implement the cleanup steps in the teardown method, write pass if there are no specific steps;
219+
- Test steps are named in the form of `step1, step2, ...`, the number at the end is the execution order;
220+
- The `TIMEOUT` attribute defines the maximum execution time of the testcase(unit: `seconds`), the testcase will be forced to end and the result will be set to TIMEOUT if it exceeds the time limit;
221+
- When `FAILFAST` attribute is *True*, the subsequent test steps will be skipped and the teardown will be executed immediately if a test step fails;
222+
- The `TAGS` attribute defines the testcase *tags*, which can be used to filter testcases to be executed in the testset;
223+
224+
## Test libraries development
225+
226+
Test libraries are stored in the `lib` subdirectory, write the test libraries according to the business requirements, import and use them in the testcases.
227+
228+
## Plugins
229+
230+
| Name | Description |
231+
|--------------------------------------------------------------------|---------------------------------------|
232+
| [xbot.plugins.ssh](https://github.com/zhaowcheng/xbot.plugins.ssh) | SSH library for xbot.framework |
233+
| xbot.plugins.http(`planning`) | HTTP library for xbot.framework |
234+
| xbot.plugins.wui(`planning`) | WebUI library for xbot.framework |
235+
| xbot.plugins.gui(`planning`) | GUI library for xbot.framework |
236+
| xbot.plugins.pgsql(`planning`) | PostgreSQL library for xbot.framework |

0 commit comments

Comments
 (0)