At Aug 15 A.

This commit is contained in:
zhaoyafan 2022-08-15 09:47:38 +08:00
parent 15b21f25a5
commit 75e6d8b79e
6 changed files with 237 additions and 195 deletions

View File

@ -1,9 +1,95 @@
import re, pymysql.cursors import pymysql.cursors
def char_width(string):
iChineseChar = 0
iEnglishChar = 0
for char in string:
if len(char.encode("utf-8")) > 2:
iChineseChar += 1
else:
iEnglishChar += 1
return (iChineseChar * 2) + iEnglishChar
def char_equal_width(string, length):
endadd = ""
if char_width(string) > length:
length = length - 2
endadd = ".."
new_char = ""
new_char_len = 0
for i in range(len(string)):
this = string[i]
this_len = char_width(this)
if new_char_len + this_len > length:
break
else:
new_char += this
new_char_len += this_len
a = length - new_char_len
new_char += a * "\x20"
new_char_len += a
new_char += endadd
new_char_len += char_width(endadd)
return new_char
def char_line(str_list, len_list):
o = ""
l = len(str_list)
for i in range(l):
this = str(str_list[i])
if i == 0:
o += "|"
if i >= 0:
o += " " + char_equal_width(this, len_list[i]) + " " + "|"
if i == (l - 1):
o += "\n"
return o
def show_table(table_head: list, table_body: list, max_char_line=5):
table_body.insert(0, table_head)
o = ""
width_list = [
max(m) if max(m) <= 20 else 20
for m in [
[char_width(str(value[i])) for value in table_body]
for i in range(len(table_head))
]
]
horizontal = ""
l = len(table_head)
for i in range(l):
if i == 0:
horizontal += "+"
if i >= 0:
horizontal += "-" * (width_list[i] + 2) + "+"
if i == (l - 1):
horizontal += "\n"
h = len(table_body)
l = h if h <= (max_char_line + 1) else (max_char_line + 1)
for i in range(l):
this = table_body[i]
if i == 0:
o += horizontal
if i >= 0:
o += char_line(this, width_list)
if i == 0:
o += horizontal
if i == (l - 1):
o += horizontal
if i == (l - 1) and h > l:
o += str(h - 1) + " rows in set, the rest have been omitted." + "\n"
return o
class MySQL: class MySQL:
__conn__ = None __conn__ = None
__curr__ = None __curr__ = None
__sqls__ = None
__data__ = None
def __init__(self, **kwargs): def __init__(self, **kwargs):
if kwargs: if kwargs:
@ -34,6 +120,7 @@ class MySQL:
def execute(self, *args): def execute(self, *args):
if self.__curr__ is None: if self.__curr__ is None:
raise Exception('连接不存在 | Connection does not exist.') raise Exception('连接不存在 | Connection does not exist.')
self.__sqls__ = str(*args)
self.__curr__.execute(*args) self.__curr__.execute(*args)
return self return self
@ -42,10 +129,26 @@ class MySQL:
raise Exception('连接不存在 | Connection does not exist.') raise Exception('连接不存在 | Connection does not exist.')
return self.__curr__.rowcount return self.__curr__.rowcount
def brief(self):
if self.__curr__ is None:
raise Exception('连接不存在 | Connection does not exist.')
if not self.__sqls__:
send = ''
else:
send = self.__sqls__
if not self.__data__:
recv = ''
else:
data = self.__data__
recv = show_table([str(k) for k in data[0].keys()], [[v for k, v in data[i].items()] for i in range(len(data))], 5)
return '[->]' + '\n' + send + '\n' + '[<-]' + '\n' + recv
def fetchall(self): def fetchall(self):
if self.__curr__ is None: if self.__curr__ is None:
raise Exception('连接不存在 | Connection does not exist.') raise Exception('连接不存在 | Connection does not exist.')
return self.__curr__.fetchall() res = self.__curr__.fetchall()
self.__data__ = res
return res
def fetchone(self): def fetchone(self):
if self.__curr__ is None: if self.__curr__ is None:

View File

@ -721,7 +721,7 @@ function html_escape(s) {
<td colspan='5' align='center'> <td colspan='5' align='center'>
<button id='btn_%(tid)s' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_%(tid)s,#div_%(tid)s_screenshot'>%(status)s</button> <button id='btn_%(tid)s' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_%(tid)s,#div_%(tid)s_screenshot'>%(status)s</button>
<div id='div_%(tid)s' class="collapse in"> <div id='div_%(tid)s' class="collapse in">
<pre style="text-align:left;font-size:12px;color:%(pre_color)s">%(script)s</pre> <pre style="text-align:left;font-family:monospace;font-size:12px;color:%(pre_color)s">%(script)s</pre>
</div> </div>
</td> </td>
<td class="text-center" style="vertical-align: middle"> <td class="text-center" style="vertical-align: middle">
@ -741,7 +741,7 @@ function html_escape(s) {
<td colspan='5' align='center'> <td colspan='5' align='center'>
<button id='btn_%(tid)s' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_%(tid)s'>%(status)s</button> <button id='btn_%(tid)s' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_%(tid)s'>%(status)s</button>
<div id='div_%(tid)s' class="collapse in"> <div id='div_%(tid)s' class="collapse in">
<pre style="text-align:left;font-size:12px;color:%(pre_color)s">%(script)s</pre> <pre style="text-align:left;font-family:monospace;font-size:12px;color:%(pre_color)s">%(script)s</pre>
</div> </div>
</td> </td>
<td class='%(style)s' style="vertical-align: middle"></td> <td class='%(style)s' style="vertical-align: middle"></td>

View File

@ -229,7 +229,7 @@
series: [{ series: [{
name: '通过', name: '通过',
color: '#64bb64', color: '#64bb64',
data: [5] data: [1]
}, { }, {
name: '失败', name: '失败',
color: '#f16d7e', color: '#f16d7e',
@ -237,7 +237,7 @@
}, { }, {
name: '错误', name: '错误',
color: '#fdc68c', color: '#fdc68c',
data: [1] data: [0]
}] }]
}) })
// 增加饼状图 // 增加饼状图
@ -291,7 +291,7 @@
innerSize: '80%', innerSize: '80%',
name: '比例', name: '比例',
data: [ data: [
['通过', 5], ['失败', 0], ['错误', 1] ['通过', 1], ['失败', 0], ['错误', 0]
] ]
}] }]
}, function(c) { }, function(c) {
@ -438,15 +438,15 @@ function html_escape(s) {
<div id="testinfo" style="max-width: 360px; width: auto; float: left;"> <div id="testinfo" style="max-width: 360px; width: auto; float: left;">
<h1 style="margin: 5px 0px 10px 0px; font-family: Microsoft YaHei;">测试报告</h1> <h1 style="margin: 5px 0px 10px 0px; font-family: Microsoft YaHei;">测试报告</h1>
<p class='attribute'><strong>开始时间 : </strong> 2022-08-12 11:13:49</p> <p class='attribute'><strong>开始时间 : </strong> 2022-08-15 00:10:16</p>
<p class='attribute'><strong>合计耗时 : </strong> 00:00:00</p> <p class='attribute'><strong>合计耗时 : </strong> 00:00:00</p>
<p class='attribute'><strong>测试结果 : </strong> 总共 6通过 5失败 0错误 1通过率 83.33%</p> <p class='attribute'><strong>测试结果 : </strong> 总共 1通过 1失败 0错误 0通过率 100.00%</p>
<p class='attribute'><strong>失败用例 : </strong></p> <p class='attribute'><strong>失败用例 : </strong></p>
<p class='attribute'><strong>错误用例 : </strong> <a class='showDetail' data-toggle='collapse' href='#errorsCaseOl' style='text-decoration: none;'>点击查看</a><ol id='errorsCaseOl' class='collapse' style='float: left; font-family: Menlo,Monaco,Consolas,monospace;'><li>main.测试用例.test0003_None</li></ol></p> <p class='attribute'><strong>错误用例 : </strong> </p>
<p class='description'></p> <p class='description'></p>
</div> </div>
@ -457,11 +457,11 @@ function html_escape(s) {
<div style="width: auto; clear: both;"> <div style="width: auto; clear: both;">
<p id='show_detail_line'> <p id='show_detail_line'>
<a class="btn btn-primary" href='javascript:showCase(0)'>概要 83.33%</a> <a class="btn btn-primary" href='javascript:showCase(0)'>概要 100.00%</a>
<a class="btn btn-success" href='javascript:showCase(2)'>通过 5</a> <a class="btn btn-success" href='javascript:showCase(2)'>通过 1</a>
<a class="btn btn-danger" href='javascript:showCase(1)'>失败 0</a> <a class="btn btn-danger" href='javascript:showCase(1)'>失败 0</a>
<a class="btn btn-warning" href='javascript:showCase(3)'>错误 1</a> <a class="btn btn-warning" href='javascript:showCase(3)'>错误 0</a>
<a class="btn btn-info" href='javascript:showCase(4)'>全部 6</a> <a class="btn btn-info" href='javascript:showCase(4)'>全部 1</a>
</p> </p>
</div> </div>
<table id='result_table' class="table table-condensed table-bordered table-hover"> <table id='result_table' class="table table-condensed table-bordered table-hover">
@ -486,121 +486,32 @@ function html_escape(s) {
<td>详细</td> <td>详细</td>
</tr> </tr>
<tr class='errorClass warning'> <tr class='passClass warning'>
<td>测试用例</td> <td>测试用例</td>
<td></td> <td></td>
<td class="text-center">6</td>
<td class="text-center">5</td>
<td class="text-center">0</td>
<td class="text-center">1</td> <td class="text-center">1</td>
<td class="text-center">0.720秒</td> <td class="text-center">1</td>
<td class="text-center"><a href="javascript:showClassDetail('c1',6)" class="detail" id='c1'>查看全部</a></td> <td class="text-center">0</td>
<td class="text-center">0</td>
<td class="text-center">0.442秒</td>
<td class="text-center"><a href="javascript:showClassDetail('c1',1)" class="detail" id='c1'>查看全部</a></td>
</tr> </tr>
<tr id='pt1_1' class='hiddenRow'> <tr id='pt1_1' class='hiddenRow'>
<td class='passedCase' style="vertical-align: middle"><div class='testcase'>test0001_None</div></td> <td class='passedCase' style="vertical-align: middle"><div class='testcase'>test0001_t1</div></td>
<td style="vertical-align: middle"></td> <td style="vertical-align: left"></td>
<td colspan='5' align='center'> <td colspan='5' align='center'><button type="button" class="btn btn-xs">通过</button></td>
<button id='btn_pt1_1' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_pt1_1'>通过</button>
<div id='div_pt1_1' class="collapse in">
<pre style="text-align:left;font-size:12px;color:#119611">pt1_1:
{}
</pre>
</div>
</td>
<td class='passedCase' style="vertical-align: middle"></td>
</tr>
<tr id='pt1_2' class='hiddenRow'>
<td class='passedCase' style="vertical-align: middle"><div class='testcase'>test0002_None</div></td>
<td style="vertical-align: middle"></td>
<td colspan='5' align='center'>
<button id='btn_pt1_2' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_pt1_2'>通过</button>
<div id='div_pt1_2' class="collapse in">
<pre style="text-align:left;font-size:12px;color:#119611">pt1_2:
{}
</pre>
</div>
</td>
<td class='passedCase' style="vertical-align: middle"></td>
</tr>
<tr id='et1_3' class='none'>
<td class='errorsCase' style="vertical-align: middle"><div class='testcase'>test0003_None</div></td>
<td style="vertical-align: middle"></td>
<td colspan='5' align='center'>
<button id='btn_et1_3' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_et1_3'>错误</button>
<div id='div_et1_3' class="collapse in">
<pre style="text-align:left;font-size:12px;color:#e54f00">et1_3:
Traceback (most recent call last):
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 579, in foo
return self._test_(index)
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 564, in test
self.test_unit(data=main_case)
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 500, in test_unit
self._assert([
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 437, in _assert
assert_parm = [eval(form[0]), eval(form[1])]
File "&lt;string&gt;", line 1, in &lt;module&gt;
File "C:\Program Files\Python310\lib\_sitebuiltins.py", line 26, in __call__
raise SystemExit(code)
SystemExit: None
</pre>
</div>
</td>
<td class='errorsCase' style="vertical-align: middle"></td>
</tr>
<tr id='pt1_4' class='hiddenRow'>
<td class='passedCase' style="vertical-align: middle"><div class='testcase'>test0004_None</div></td>
<td style="vertical-align: middle"></td>
<td colspan='5' align='center'>
<button id='btn_pt1_4' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_pt1_4'>通过</button>
<div id='div_pt1_4' class="collapse in">
<pre style="text-align:left;font-size:12px;color:#119611">pt1_4:
{}
</pre>
</div>
</td>
<td class='passedCase' style="vertical-align: middle"></td>
</tr>
<tr id='pt1_5' class='hiddenRow'>
<td class='passedCase' style="vertical-align: middle"><div class='testcase'>test0005_None</div></td>
<td style="vertical-align: middle"></td>
<td colspan='5' align='center'>
<button id='btn_pt1_5' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_pt1_5'>通过</button>
<div id='div_pt1_5' class="collapse in">
<pre style="text-align:left;font-size:12px;color:#119611">pt1_5:
{'var2': 'nginx'}
</pre>
</div>
</td>
<td class='passedCase' style="vertical-align: middle"></td>
</tr>
<tr id='pt1_6' class='hiddenRow'>
<td class='passedCase' style="vertical-align: middle"><div class='testcase'>test0006_None</div></td>
<td style="vertical-align: middle"></td>
<td colspan='5' align='center'>
<button id='btn_pt1_6' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_pt1_6'>通过</button>
<div id='div_pt1_6' class="collapse in">
<pre style="text-align:left;font-size:12px;color:#119611">pt1_6:
{'var2': 'nginx', 'var3': '101', 'var4': '阿凡\n凡凡', 'var5': '{"name": "小红", "age": 22}'}
</pre>
</div>
</td>
<td class='passedCase' style="vertical-align: middle"></td> <td class='passedCase' style="vertical-align: middle"></td>
</tr> </tr>
<tr id='total_row' class="text-center active"> <tr id='total_row' class="text-center active">
<td colspan='2'>总计</td> <td colspan='2'>总计</td>
<td>6</td>
<td>5</td>
<td>0</td>
<td>1</td> <td>1</td>
<td>0.720秒</td> <td>1</td>
<td>通过83.33%</td> <td>0</td>
<td>0</td>
<td>0.442秒</td>
<td>通过100.00%</td>
</tr> </tr>
</table> </table>

View File

@ -114,19 +114,21 @@ class TestCase:
tabs = { tabs = {
"HTTPConf": { "HTTPConf": {
"fixed": {}, "fixed": {},
"views": "A4:F*", "views": "A4:H*",
"field": [ "field": [
"Name", "Name",
"Scheme", "Scheme",
"Host", "Host",
"DefaultHeader", "DefaultHeader",
"Timeout", "Timeout",
"Session" "Session",
"Proxies",
"IgnoreSSLCertError"
] ]
}, },
"DataBase": { "DataBase": {
"fixed": {}, "fixed": {},
"views": "H4:N*", "views": "J4:P*",
"field": [ "field": [
"Name", "Name",
"Host", "Host",
@ -155,7 +157,7 @@ class TestCase:
"Flag", "Flag",
"PreExecCase", "PreExecCase",
"PreExecRule", "PreExecRule",
"Module", "CaseModule",
"CaseId", "CaseId",
"CaseTitle", "CaseTitle",
"CaseDesc", "CaseDesc",
@ -182,7 +184,7 @@ class TestCase:
"BaseExtract", "BaseExtract",
"BaseAssertData", "BaseAssertData",
"BaseAssertRows", "BaseAssertRows",
"DataSet", "DataFileSet",
"Author", "Author",
"TestTime", "TestTime",
"TestResult" "TestResult"
@ -323,8 +325,7 @@ class TestCase:
else: else:
return False return False
@staticmethod def _sub_variable(self, text, vars_dict):
def _sub_variable(text, vars_dict):
if not isinstance(text, str): if not isinstance(text, str):
return text return text
for variable_name in re.findall('\${(.*?)}', text): for variable_name in re.findall('\${(.*?)}', text):
@ -332,6 +333,8 @@ class TestCase:
value = vars_dict[variable_name] value = vars_dict[variable_name]
except: except:
value = '' value = ''
if self._is_nan(value) or value is None:
value = ''
text = text.replace('${%s}' % variable_name, str(value)) text = text.replace('${%s}' % variable_name, str(value))
return text return text
@ -363,29 +366,29 @@ class TestCase:
import math import math
if value is None: if value is None:
return '' return ''
try: if isinstance(value, (float, int)) and str(value) == str(float('NaN')):
if math.isnan(value): return ''
return '' if isinstance(value, (float,)) and math.modf(value)[0] == 0:
except:
pass
if isinstance(value, float) and math.modf(value)[0] == 0:
return str(int(value)) return str(int(value))
return str(value) return str(value)
@staticmethod @staticmethod
def _to_number(value): def _to_number(value):
import math
if not value: if not value:
return 0 return 0
if value is True: if value is True:
return 1 return 1
try: if isinstance(value, (float, int)) and str(value) == str(float('NaN')):
if math.isnan(value): return 0
return 0
except:
pass
return int(float(value)) return int(float(value))
@staticmethod
def _is_nan(value):
if isinstance(value, (float, int)) and str(value) == str(float('NaN')):
return True
else:
return False
def _extract_variable(self, extract, vars_dict: dict, domain: str | list | dict): def _extract_variable(self, extract, vars_dict: dict, domain: str | list | dict):
if not extract: return None if not extract: return None
if not isinstance(extract, (list, dict)): if not isinstance(extract, (list, dict)):
@ -451,11 +454,10 @@ class TestCase:
actual = str(actual) actual = str(actual)
assert actual == expect, '%s != %s' % (actual, expect) assert actual == expect, '%s != %s' % (actual, expect)
def test_unit(self, data): def _test_unit(self, data, main=None):
if data['HTTPUri']: if data['HTTPUri']:
if not data['HTTPChannel']: if not data['HTTPChannel']:
raise Exception('channel not set') raise Exception('channel not set')
# 创建请求
http = self.h.where((self.h['Name'] == data['HTTPChannel']), inplace=False).dropna(how='all').reset_index(drop=True, inplace=False).loc[0].to_dict() http = self.h.where((self.h['Name'] == data['HTTPChannel']), inplace=False).dropna(how='all').reset_index(drop=True, inplace=False).loc[0].to_dict()
res_kwargs = { res_kwargs = {
'method': data['HTTPMethod'], 'method': data['HTTPMethod'],
@ -468,9 +470,9 @@ class TestCase:
'cookie': self._sub_variable_auto(auto_decode(data['HTTPCookie'])), 'cookie': self._sub_variable_auto(auto_decode(data['HTTPCookie'])),
'auth': None, 'auth': None,
'timeout': self._to_number(http['Timeout']) or 15, 'timeout': self._to_number(http['Timeout']) or 15,
'proxy': None, 'proxy': self._to_string(http['Proxies']),
'auto_redirect': self._match_bool(data['HTTPRedirect']), 'auto_redirect': self._match_bool(data['HTTPRedirect']),
'ignore_cert_error': False, 'ignore_cert_error': self._match_bool(http['IgnoreSSLCertError']),
'debug': True 'debug': True
} }
res_kwargs['header'].update((auto_decode(http['DefaultHeader']) or {})) res_kwargs['header'].update((auto_decode(http['DefaultHeader']) or {}))
@ -485,7 +487,7 @@ class TestCase:
res_kwargs['file'] = locals().setdefault('f', self._sub_variable_auto(auto_decode( res_kwargs['file'] = locals().setdefault('f', self._sub_variable_auto(auto_decode(
data['HTTPParamOfFile']))) and {k: open(os.path.abspath(os.path.join(self.dirs, './%s' % v)), 'rb') for k, v in locals().get('f').items()} data['HTTPParamOfFile']))) and {k: open(os.path.abspath(os.path.join(self.dirs, './%s' % v)), 'rb') for k, v in locals().get('f').items()}
res = [self.request, self.session][self._match_bool(http['Session'])].http(**res_kwargs) res = [self.request, self.session][self._match_bool(http['Session'])].http(**res_kwargs)
# 创建变量 log.d("\n" + res['brief'])
hvar = { hvar = {
'Status': ReText(res['status'] or ''), 'Status': ReText(res['status'] or ''),
'Reason': ReText(res['reason'] or ''), 'Reason': ReText(res['reason'] or ''),
@ -494,9 +496,7 @@ class TestCase:
'Body': ReText(res['text'] or ''), 'Body': ReText(res['text'] or ''),
'Json': ReDict(res['json'] or {}), 'Json': ReDict(res['json'] or {}),
} }
# 提取变量
self._extract_variable(extract=data['HTTPExtract'], vars_dict=hvar, domain='global') self._extract_variable(extract=data['HTTPExtract'], vars_dict=hvar, domain='global')
# 开始断言
self._assert([ self._assert([
{'expect': data['HTTPAssertStatus'], 'actual': hvar['Status']}, {'expect': data['HTTPAssertStatus'], 'actual': hvar['Status']},
{'expect': data['HTTPAssertReason'], 'actual': hvar['Reason']}, {'expect': data['HTTPAssertReason'], 'actual': hvar['Reason']},
@ -509,61 +509,41 @@ class TestCase:
if not data['BaseChannel']: if not data['BaseChannel']:
raise Exception('channel not set') raise Exception('channel not set')
base = self.b.where((self.b['Name'] == data['BaseChannel']), inplace=False).dropna(how='all').reset_index(drop=True, inplace=False).loc[0].to_dict() base = self.b.where((self.b['Name'] == data['BaseChannel']), inplace=False).dropna(how='all').reset_index(drop=True, inplace=False).loc[0].to_dict()
# 创建请求
conn = MySQL().connect( conn = MySQL().connect(
host=base['Host'], port=int(base['Port']), host=base['Host'], port=int(base['Port']),
user=base['User'], password=base['Password'], database=base['Database'], charset=base['Charset'], cursor='Dict' user=base['User'], password=base['Password'], database=base['Database'], charset=base['Charset'], cursor='Dict'
) )
conn.execute(data['BaseSql']) conn.execute(data['BaseSql'])
# 创建变量
bvar = { bvar = {
'Data': ReList(conn.fetchall() or []), 'Data': ReList(conn.fetchall() or []),
'Rows': conn.count() or 0 'Rows': conn.count() or 0
} }
# 提取变量 log.d("\n" + conn.brief())
self._extract_variable(extract=data['BaseExtract'], vars_dict=bvar, domain='global') self._extract_variable(extract=data['BaseExtract'], vars_dict=bvar, domain='global')
# for var_name, var_value in {
# '_Data': ReList(conn.fetchall() or []),
# '_Rows': conn.count() or 0
# }.items():
# locals().__setitem__(var_name, var_value)
# for k, v in (auto_decode(data['DatabaseExtract']) or {}).items():
# d = re.findall('^([0-9A-Za-z_]+).*?', v)[0]
# self._g[str(k)] = str(eval('_' + v.replace(d, d.title(), 1)))
# 开始断言
self._assert([ self._assert([
{'expect': data['BaseAssertData'], 'actual': bvar['Data']}, {'expect': data['BaseAssertData'], 'actual': bvar['Data']},
{'expect': data['BaseAssertRows'], 'actual': bvar['Rows']}, {'expect': data['BaseAssertRows'], 'actual': bvar['Rows']},
], self.assert_list) ], self.assert_list)
print(self._g) def test(self, index, update_global=None, update_locals=None):
if isinstance(update_global, (dict,)):
# expect = self._to_string(data['HTTPAssertStatus']) self._g.update(update_global)
# if expect: if isinstance(update_locals, (dict,)):
# opers = [" == ", " != ", " >= ", " <= ", " > ", " < ", " in ", " not in "] self._l.update(update_locals)
# opers_flag = 0
# for v in opers:
# if v in expect:
# opers_flag = 1
# break
# if opers_flag:
# contrast = list(filter(lambda x: x, expect.split("\n")))
# for contr in contrast:
# exec('assert ' + self._sub_variable_auto(contr).replace('$', str(res['status'])))
# else:
# actual = str(res['status'])
# try:
# assert expect == actual
# except AssertionError as e:
# raise AssertionError(str(expect) + ' == ' + str(actual))
# # sys.stderr.write()
def test(self, index):
# print(view_case.loc[index])
main_case = dict(self.c.loc[index].to_dict()) main_case = dict(self.c.loc[index].to_dict())
self.test_unit(data=main_case) prex_list = list(filter(lambda x: x, [value.strip() for value in (main_case['PreExecCase'] or '').replace(',', "\n").split("\n")]))
for id in prex_list:
data = self.c.where((self.c['CaseId'] == id), inplace=False).dropna(how='all').reset_index(drop=True, inplace=False).loc[0].to_dict()
if data['PreExecCase'] or data['PreExecRule']:
raise Exception('')
if data['DataFileSet']:
raise Exception('')
self._test_unit(data=data)
self._test_unit(data=main_case, main=True)
self._l.clear()
def main(self): def main(self):
from pandas import read_csv
class ClassTestCase(unittest.TestCase): class ClassTestCase(unittest.TestCase):
pass pass
@ -571,15 +551,57 @@ class TestCase:
ClassTestCase._test_ = self.test ClassTestCase._test_ = self.test
serial = 0 serial = 0
for i in range(len(self.c)): for i in range(len(self.c)):
thisCase = self.c.loc[i].to_dict() data = self.c.loc[i].to_dict()
if not self._match_case_type(thisCase['Flag']) == 10 and self._match_leve_run(thisCase['CaseLevel']): continue if not self._match_case_type(data['Flag']) == 10 and self._match_leve_run(data['CaseLevel']): continue
serial += 1 serial += 1
filename = data['DataFileSet'] or ''
if filename:
data_file = read_csv(os.path.abspath(os.path.join(self.dirs, './%s' % filename)), keep_default_na=False)
data_file_rows = len(data_file)
data_file_flag = 1
else:
data_file = None
data_file_rows = 0
data_file_flag = 0
j = 0
while j < data_file_rows or data_file_flag == 0:
match data_file_flag:
case 1:
vars_data = data_file.loc[j].to_dict()
func_docs = str(data['CaseTitle'] or '') + '_' + '_'.join([str(v) for k, v in vars_data.items()])[:32]
func_name = 'test%s_%s_%s' % (str('%04d' % serial), str(data['CaseId']), str('%04d' % (j + 1)))
once_do_break = 0
case _:
vars_data = None
func_docs = str(data['CaseTitle'] or '')
func_name = 'test%s_%s' % (str('%04d' % serial), str(data['CaseId']))
once_do_break = 1
def foo(self, index=i): def func(self, index=i, update_global=None, update_locals=vars_data):
return self._test_(index) return self._test_(index=index, update_global=update_global, update_locals=update_locals)
func.__doc__ = func_docs
type.__setattr__(ClassTestCase, func_name, func)
j += 1
if once_do_break: break
# if filename:
# data_file = read_csv(os.path.join(self.dirs, './%s' % filename), keep_default_na=False)
# for j in range(len(data_file)):
# vars_data = data_file.loc[j].to_dict()
#
# def func(self, index=i, update_global=None, update_locals=vars_data):
# return self._test_(index=index, update_global=update_global, update_locals=update_locals)
#
# func.__doc__ = (data['CaseTitle'] or '') + '_' + '_'.join([str(v) for k, v in vars_data.items()])[:32]
# type.__setattr__(ClassTestCase, 'test%s_%s_%s' % (str('%04d' % serial), str(data['CaseId']), str('%04d' % (j+1))), func)
# else:
# def func(self, index=i, update_global=None, update_locals=None):
# return self._test_(index=index, update_global=update_global, update_locals=update_locals)
#
# func.__doc__ = data['CaseTitle']
# type.__setattr__(ClassTestCase, 'test%s_%s' % (str('%04d' % serial), str(data['CaseId'])), func)
foo.__doc__ = thisCase['CaseTitle']
exec('ClassTestCase.test%s_%s = foo' % (str('%04d' % serial), str(thisCase['CaseId'])))
return ClassTestCase return ClassTestCase
@ -593,5 +615,5 @@ if __name__ == '__main__':
httpconf='请求配置', httpconf='请求配置',
database='请求配置' database='请求配置'
).main(), prefix='test')) ).main(), prefix='test'))
HTMLTestRunner(verbosity=5, report=os.path.abspath(os.path.join(os.path.dirname(__file__), './1.html'))).run( HTMLTestRunner(verbosity=1, report=os.path.abspath(os.path.join(os.path.dirname(__file__), './1.html'))).run(
test_suite) test_suite)

View File

@ -1,11 +1,16 @@
def assertPreWith(string: str, sub: str): import pandas as pd
if not string.startswith(sub): # from Base.Class.Yaml import *
raise AssertionError('%s does not starts with %s' % (string, sub)) # from pandas import read_csv
# df = read_csv("D:/Desktop/新建 XLSX 工作表.csv", keep_default_na=False)
# print(df.loc[2].to_dict())
from pandas.core.frame import DataFrame
from Base.Class.Database import *
conn = MySQL().connect(host='sdm821105491.my3w.com', port=3306, user='sdm821105491', password='1234ABCDabcd', database='sdm821105491_db', charset='utf8')
conn.execute('select gid,title,date,content from %s;' % 'emlog_blog')
data = conn.fetchall()
# print(data)
print(conn.brief())
def assertSufWith(string: str, sub: str):
if not string.endswith(sub):
raise AssertionError('%s does not ends with %s' % (string, sub))
assertSufWith('admin 123456 ...', '...')
assertPreWith('admin 123456 ...', 'admin 1')

1
main6.py Normal file
View File

@ -0,0 +1 @@
print(list(filter(lambda x: x, [value.strip() for value in ( or '').replace(',',"\n").split("\n")])))