├── .env
├── babel.config.js
├── public
├── favicon.ico
└── index.html
├── src
├── assets
│ ├── image
│ │ ├── logo.png
│ │ ├── favicon.png
│ │ ├── login-bg.png
│ │ ├── teprunner.png
│ │ ├── user-icon.png
│ │ └── file-template.png
│ ├── fonts
│ │ ├── fontawesome-webfont.674f50d2.eot
│ │ ├── fontawesome-webfont.b06871f2.ttf
│ │ ├── fontawesome-webfont.af7ae505.woff2
│ │ └── fontawesome-webfont.fee66e71.woff
│ ├── js
│ │ └── highlight.js
│ ├── iconfont
│ │ └── iconfont.js
│ └── css
│ │ └── common.scss
├── views
│ ├── console
│ │ ├── index.vue
│ │ ├── ProjectManagement.vue
│ │ ├── AddProject.vue
│ │ ├── userManagement.vue
│ │ └── addUser.vue
│ ├── teprunner
│ │ ├── index.vue
│ │ ├── case
│ │ │ ├── CaseView.vue
│ │ │ ├── WriteDown.vue
│ │ │ ├── CaseEditor.vue
│ │ │ ├── CaseResult.vue
│ │ │ └── CaseManagement.vue
│ │ ├── AddEnvVar.vue
│ │ ├── plan
│ │ │ ├── CaseResult.vue
│ │ │ ├── PlanResult.vue
│ │ │ ├── PlanEditor.vue
│ │ │ ├── CaseList.vue
│ │ │ └── PlanManagement.vue
│ │ ├── FixtureEditor.vue
│ │ ├── Fixture.vue
│ │ ├── EnvVar.vue
│ │ ├── Grammar.vue
│ │ └── GitSync.vue
│ ├── login
│ │ └── index.vue
│ └── home
│ │ └── index.vue
├── components
│ ├── IconFont.vue
│ ├── Pagination.vue
│ ├── WrapComponent.vue
│ ├── NavLeft.vue
│ ├── ProjectEnv.vue
│ └── SelectionPanel.vue
├── App.vue
├── main.js
├── utils
│ ├── const.js
│ └── commonMethods.js
├── service
│ └── axios.js
└── router
│ └── index.js
├── README
├── image-20210306090248863.png
└── image-20210821103333142.png
├── deploy
├── Dockerfile
├── nginx.conf
└── build.sh
├── .gitignore
├── README.md
├── vue.config.js
└── package.json
/.env:
--------------------------------------------------------------------------------
1 | VUE_APP_apiServer=http://127.0.0.1:8000
2 | VUE_APP_wsServer=ws://127.0.0.1:8000
3 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"],
3 | };
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/assets/image/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/src/assets/image/logo.png
--------------------------------------------------------------------------------
/src/assets/image/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/src/assets/image/favicon.png
--------------------------------------------------------------------------------
/src/assets/image/login-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/src/assets/image/login-bg.png
--------------------------------------------------------------------------------
/src/assets/image/teprunner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/src/assets/image/teprunner.png
--------------------------------------------------------------------------------
/src/assets/image/user-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/src/assets/image/user-icon.png
--------------------------------------------------------------------------------
/README/image-20210306090248863.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/README/image-20210306090248863.png
--------------------------------------------------------------------------------
/README/image-20210821103333142.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/README/image-20210821103333142.png
--------------------------------------------------------------------------------
/src/assets/image/file-template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/src/assets/image/file-template.png
--------------------------------------------------------------------------------
/deploy/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx:latest
2 | WORKDIR /usr/share/nginx/html
3 | COPY ./dist ./
4 | COPY ./deploy/nginx.conf /etc/nginx/conf.d/default.conf
5 |
--------------------------------------------------------------------------------
/src/assets/fonts/fontawesome-webfont.674f50d2.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/src/assets/fonts/fontawesome-webfont.674f50d2.eot
--------------------------------------------------------------------------------
/src/assets/fonts/fontawesome-webfont.b06871f2.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/src/assets/fonts/fontawesome-webfont.b06871f2.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/fontawesome-webfont.af7ae505.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/src/assets/fonts/fontawesome-webfont.af7ae505.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/fontawesome-webfont.fee66e71.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dongfanger/teprunner-frontend/HEAD/src/assets/fonts/fontawesome-webfont.fee66e71.woff
--------------------------------------------------------------------------------
/deploy/nginx.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | location / {
4 | root /usr/share/nginx/html;
5 | index index.html;
6 | }
7 | location /api {
8 | proxy_pass http://172.16.25.131:8099;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/src/views/console/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 | 选择项目和环境。 17 |
18 |24 | 点击下载zip文件并解压。 25 |
26 |32 | 在tests目录编写pytest用例。 33 |
34 |37 | 说明:所有环境变量和fixtures均会导出,不包括测试用例。 38 |
39 |13 | 创建人: 14 | {{ this.caseForm.creatorNickname }} 15 |
16 |17 | 运行结果: 18 | {{ this.caseForm.result }} 19 |
20 |21 | 运行耗时: 22 | {{ this.caseForm.elapsed }} 23 |
24 |25 | 运行环境: 26 | {{ this.caseForm.runEnv }} 27 |
28 |29 | 运行人: 30 | {{ this.caseForm.runUserNickname }} 31 |
32 |33 | 运行时间: 34 | {{ this.caseForm.runTime }} 35 |
36 |测试平台
7 |5 | 语法说明 6 |
7 |
14 | key-value字符串。比如域名:
15 |
16 | 变量名domain,变量值https://qa.com
17 |
18 | 通过env_vars.domain使用
19 |
26 | 接口管理、数据管理等,供测试用例调用。比如登录接口:
27 |
28 |
from tep.client import request
30 | from tep.fixture import *
31 |
32 |
33 | def _jwt_headers(token):
34 | return {"Content-Type": "application/json", "authorization": f"Bearer {token}"}
35 |
36 |
37 | @pytest.fixture(scope="session")
38 | def login(env_vars):
39 | # Code your login
40 | logger.info("Administrator login")
41 | response = request(
42 | "post",
43 | url=env_vars.domain + "/api/users/login",
44 | headers={"Content-Type": "application/json"},
45 | json={
46 | "username": "dongfanger",
47 | "password": "123",
48 | }
49 | )
50 | assert response.status_code < 400
51 | response_token = jmespath.search("token", response.json())
52 | super_admin_id = jmespath.search("user.id", response.json())
53 |
54 | class Clazz:
55 | token = response_token
56 | jwt_headers = _jwt_headers(response_token)
57 | admin_id = super_admin_id
58 |
59 | return Clazz
60 |
61 | 67 | 单个接口 68 |
69 |import jmespath
70 | from loguru import logger
71 |
72 | from tep.client import request
73 |
74 |
75 | def test_post(faker_ch, env_vars, login):
76 | # 描述
77 | logger.info("test post")
78 | # 数据
79 | fake = faker_ch
80 | # 请求
81 | response = request(
82 | "post",
83 | url=env_vars.domain + "/api/users",
84 | headers=login.jwt_headers,
85 | json={
86 | "name": fake.name()
87 | }
88 | )
89 | # 断言
90 | assert response.status_code < 400
91 | # 提取
92 | user_id = jmespath.search("id", response.json())
93 |
94 | 96 | 多个接口--增删改查 97 |
98 |import jmespath
99 | from loguru import logger
100 | from tep.client import request
101 |
102 |
103 | def test(faker_ch, login, env_vars):
104 | fake = faker_ch
105 | logger.info("新增")
106 | nickname = fake.name()
107 | phone = fake.phone_number()
108 | response = request(
109 | "post",
110 | url=env_vars.domain + "/api/users",
111 | headers=login.jwt_headers,
112 | json={
113 | "nickname": nickname, "phone": phone
114 | }
115 | )
116 | assert response.status_code < 400
117 | user_id = jmespath.search("id", response.json())
118 | created_at = jmespath.search("createdAt", response.json())
119 | updated_at = jmespath.search("updatedAt", response.json())
120 |
121 | logger.info("查询")
122 | response = request(
123 | "get",
124 | url=env_vars.domain + "/api/users",
125 | headers=login.jwt_headers,
126 | params={
127 | "page": 1,
128 | "perPage": 10,
129 | "keyword": nickname
130 | }
131 | )
132 | assert response.status_code < 400
133 |
134 | logger.info("修改")
135 | nickname_new = fake.name()
136 | phone_new = fake.phone_number()
137 | response = request(
138 | "put",
139 | url=env_vars.domain + f"/api/users/{user_id}",
140 | headers=login.jwt_headers,
141 | json={
142 | "id": user_id, "createdAt": created_at, "updatedAt": updated_at,
143 | "phone": phone_new, "nickname": nickname_new
144 | }
145 | )
146 | assert response.status_code < 400
147 | logger.info(f"用户姓名手机 {nickname} {phone} 修改后 {nickname_new} {phone_new}")
148 |
149 | logger.info("删除")
150 | response = request(
151 | "delete",
152 | url=env_vars.domain + f"/api/users/{user_id}",
153 | headers=login.jwt_headers
154 | )
155 | assert response.status_code < 400
156 |
157 | 163 | get 164 |
165 |# 不带参数
166 | request("get", url=env_vars.domain + "/api/xxx", headers=headers)
167 |
168 | # json参数
169 | request("get", url=env_vars.domain + "/api/xxx", headers=headers, params={})
170 |
171 | # queryset
172 | request("get", url=env_vars.domain + "/api/xxx?a=1&b=2", headers=headers)
173 |
174 | # json转queryset
175 | from urllib.parse import urlencode
176 |
177 | query = {}
178 | request("get", url=env_vars.domain + "/api/xxx" + "?" + urlencode(query), headers=headers)
179 |
180 | 182 | post 183 |
184 |# json参数
185 | request("post", url=env_vars.domain + "/api/xxx", headers=headers, json={})
186 |
187 | # dict参数
188 | request("post", url=env_vars.domain + "/api/xxx", headers=headers, data={})
189 |
190 | 192 | put 193 |
194 |request("put", url=env_vars.domain + "/api/xxx", headers=headers, json={})
195 |
196 | 198 | delete 199 |
200 |request("delete", url=env_vars.domain + f"/api/xxx", headers=headers)
201 |
202 | 11 | 计划名称: 12 | {{ planInfo.name }} 13 |
14 |15 | 所属项目: 16 | {{ projectName }} 17 |
18 |19 | 查询类型: 20 | {{ this.searchTypeName }} 21 |
22 |38 | 1.单向同步:只能从Git拉取用例到平台,平台用例无法上传到Git。 39 |
40 || 操作 | 45 |Git用例 | 46 |平台用例 | 47 |
| 查看 | 50 |√ | 51 |√ | 52 |
| 运行 | 55 |√ | 56 |√ | 57 |
| 编辑 | 60 |× | 61 |√ | 62 |
| 删除 | 65 |× | 66 |√ | 67 |
| 复制 | 70 |√ | 71 |√ | 72 |
80 | 3.同步内容:只同步测试用例,不同步环境变量和fixtures。
81 |
82 |
#!/usr/bin/python
87 | # encoding=utf-8
88 |
89 | """
90 | @Author : Don
91 | @Date : ${DATE} ${TIME}
92 | @Desc :
93 | """
94 | 35 | crontab表达式,共5位,最小粒度为分钟 36 | * * * * * 37 | - - - - - 38 | | | | | | 39 | | | | | +----- 星期中星期几 (0 - 6) (星期天 为0) 40 | | | | +---------- 月份 (1 - 12) 41 | | | +--------------- 一个月中的第几天 (1 - 31) 42 | | +-------------------- 小时 (0 - 23) 43 | +------------------------- 分钟 (0 - 59) 44 | 【每分钟】 45 | * * * * * 46 | 【每小时的第一分】 47 | 1 * * * * 48 | 【每天7:50】 49 | 50 7 * * * 50 | 【每两个小时】 51 | 0 */2 * * * 52 | 【每月1号和15号】 53 | 0 0 1,15 * * 54 | 【每周一至周五3点钟】 55 | 00 03 * * 1-5 56 | 【每月的1、11、21、31日的6:30】 57 | 30 6 */10 * * 58 | 【每月每天的午夜0点20分, 2点20分, 4点20分】 59 | 20 0-23/2 * * * 60 | 【在12月内, 每天的早上6点到12点,每隔3个小时0分钟】 61 | 0 6-12/3 * 12 * 62 |63 |
14 | 创建人: 15 | {{ this.caseForm.creatorNickname }} 16 |
17 |18 | 运行结果: 19 | {{ this.caseForm.result }} 20 |
21 |22 | 运行耗时: 23 | {{ this.caseForm.elapsed }} 24 |
25 |26 | 运行环境: 27 | {{ this.caseForm.runEnv }} 28 |
29 |30 | 运行人: 31 | {{ this.caseForm.runUserNickname }} 32 |
33 |34 | 运行时间: 35 | {{ this.caseForm.runTime }} 36 |
37 |10 | 计划名称: 11 | {{ planInfo.name }} 12 |
13 |14 | 所属项目: 15 | {{ projectName }} 16 |
17 |
6 | 测试平台
7 | 注:{{ pwdRegText }}
87 | 91 |