liumiaomiao 2 năm trước cách đây
mục cha
commit
ed18f8171f
39 tập tin đã thay đổi với 2613 bổ sung131 xóa
  1. 19 0
      .idea/dataSources.xml
  2. 6 0
      .idea/sqldialects.xml
  3. 4 0
      .idea/vcs.xml
  4. 1 0
      README.md
  5. BIN
      cases/未登录功能/__pycache__/bidsearch.cpython-38.pyc
  6. BIN
      cases/未登录功能/__pycache__/buyersearch.cpython-38.pyc
  7. 10 0
      cases/未登录功能/bidsearch.py
  8. 11 0
      cases/未登录功能/buyersearch.py
  9. BIN
      cases/登录功能/__pycache__/__st__.cpython-38.pyc
  10. BIN
      cases/登录功能/__pycache__/login.cpython-38.pyc
  11. 8 0
      cases/登录功能/__st__.py
  12. 5 5
      cases/登录功能/login.py
  13. BIN
      cases/登录功能/搜索功能/__pycache__/buyersearch.cpython-38.pyc
  14. BIN
      cases/登录功能/搜索功能/__pycache__/enterpriseSearch.cpython-38.pyc
  15. BIN
      cases/登录功能/搜索功能/__pycache__/search.cpython-38.pyc
  16. BIN
      cases/登录功能/搜索功能/__pycache__/supplySearch.cpython-38.pyc
  17. 27 0
      cases/登录功能/搜索功能/buyersearch.py
  18. 33 0
      cases/登录功能/搜索功能/enterpriseSearch.py
  19. 25 0
      cases/登录功能/搜索功能/search.py
  20. 26 0
      cases/登录功能/搜索功能/supplySearch.py
  21. BIN
      cases/登录功能/订阅/__pycache__/push_list.cpython-38.pyc
  22. 0 0
      cases/登录功能/订阅/push_list.py
  23. 13 5
      doc/test.py
  24. 90 0
      doc/zbsousuo.py
  25. BIN
      lib/__pycache__/webapi.cpython-38.pyc
  26. 110 4
      lib/webapi.py
  27. 14 21
      log/report_20230706_152619.html
  28. 21 15
      log/report_20230706_152740.html
  29. 430 0
      log/report_20230706_152946.html
  30. 19 15
      log/report_20230706_153106.html
  31. 15 22
      log/report_20230706_153139.html
  32. 19 15
      log/report_20230706_153217.html
  33. 430 0
      log/report_20230706_155630.html
  34. 481 0
      log/report_20230706_160520.html
  35. 485 0
      log/report_20230706_160543.html
  36. 31 9
      log/report_20230706_160626.html
  37. 62 8
      log/testresult.log
  38. 111 6
      log/testresult.log.1
  39. 107 6
      log/testresult.log.2

+ 19 - 0
.idea/dataSources.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
+    <data-source source="LOCAL" name="217tidb" uuid="6e5b328f-27a0-4f37-aa80-faa9a77b70e3">
+      <driver-ref>mysql.8</driver-ref>
+      <synchronize>true</synchronize>
+      <jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
+      <jdbc-url>jdbc:mysql://192.168.3.217:4000</jdbc-url>
+      <working-dir>$ProjectFileDir$</working-dir>
+    </data-source>
+    <data-source source="LOCAL" name="数据分析库" uuid="626c136a-91ee-4064-bbe8-af5a2d4789e7">
+      <driver-ref>mysql.8</driver-ref>
+      <synchronize>true</synchronize>
+      <jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
+      <jdbc-url>jdbc:mysql://192.168.3.217 :4000</jdbc-url>
+      <working-dir>$ProjectFileDir$</working-dir>
+    </data-source>
+  </component>
+</project>

+ 6 - 0
.idea/sqldialects.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="SqlDialectMappings">
+    <file url="PROJECT" dialect="MySQL" />
+  </component>
+</project>

+ 4 - 0
.idea/vcs.xml

@@ -1,6 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="VcsDirectoryMappings">
+<<<<<<< HEAD
     <mapping directory="$PROJECT_DIR$" vcs="Git" />
+=======
+    <mapping directory="" vcs="Git" />
+>>>>>>> a9e604d0c5e180d4ecd9234862a74b12c2317318
   </component>
 </project>

+ 1 - 0
README.md

@@ -0,0 +1 @@
+剑鱼接口自动化测试

BIN
cases/未登录功能/__pycache__/bidsearch.cpython-38.pyc


BIN
cases/未登录功能/__pycache__/buyersearch.cpython-38.pyc


+ 10 - 0
cases/未登录功能/bidsearch.py

@@ -0,0 +1,10 @@
+from hytest import *
+from lib.webapi import apimgr
+
+class c1:
+    name = '未登录招标搜索'
+    def teststeps(self):
+        res=apimgr.notloggedin_search()
+        code=res.status_code
+        # 设置检查点
+        CHECK_POINT('检查未登录采购单位搜索接口是否正常', code == 200)

+ 11 - 0
cases/未登录功能/buyersearch.py

@@ -0,0 +1,11 @@
+from hytest import *
+from lib.webapi import apimgr
+
+class c1:
+    name = '未登录采购单位搜索'
+    def teststeps(self):
+        res=apimgr.notloggedin_buysearch('科技')
+        r=res.json()
+        actural = r['data']['count']
+        # 设置检查点
+        CHECK_POINT('检查未登录采购单位搜索接口是否正常', actural != 0)

BIN
cases/登录功能/__pycache__/__st__.cpython-38.pyc


BIN
cases/登录功能/__pycache__/login.cpython-38.pyc


+ 8 - 0
cases/登录功能/__st__.py

@@ -0,0 +1,8 @@
+from hytest import *
+from lib.webapi import apimgr
+def suite_setup():
+    INFO('用户登录')
+    apimgr.mgr_login()
+def suite_teardown():
+    INFO('用户退出')
+    apimgr.mgr_logout()

+ 5 - 5
cases/登录功能/login.py

@@ -3,19 +3,19 @@ from lib.webapi import apimgr
 class c1:
     #测试用例名称
     name='登录接口验证'
-    # 初始化方法
-    def setup(self):
-        INFO('初始化方法')
     #测试步骤
     def teststeps(self):
         INFO('测试步骤')
         STEP(1,'第一步调用函数')    #会出现在测试报告中
         r = apimgr.mgr_login()
         res = r.json()
+        # INFO(res)
         actural = res['userInfo']['result']
         STEP(2,'第二步设置检查点')
         #设置检查点
-        CHECK_POINT('检查登录接口是否正常',actural =='ok')
+        CHECK_POINT('检查登录接口是否正常',actural =="ok")
     #清除方法
     def teardown(self):
-        INFO('清除方法')
+        INFO('用户退出')
+        apimgr.mgr_logout()
+

BIN
cases/登录功能/搜索功能/__pycache__/buyersearch.cpython-38.pyc


BIN
cases/登录功能/搜索功能/__pycache__/enterpriseSearch.cpython-38.pyc


BIN
cases/登录功能/搜索功能/__pycache__/search.cpython-38.pyc


BIN
cases/登录功能/搜索功能/__pycache__/supplySearch.cpython-38.pyc


+ 27 - 0
cases/登录功能/搜索功能/buyersearch.py

@@ -0,0 +1,27 @@
+import json
+from logging import ERROR
+
+import requests
+from hytest import *
+from lib.webapi import apimgr
+class c5:
+    #测试用例名称
+    name='采购单位搜索'
+    # 初始化方法
+    def setup(self):
+        INFO('初始化方法')
+    #测试步骤
+    def teststeps(self):
+        INFO('测试步骤')
+        STEP(1,'第一步调用函数')    #会出现在测试报告中
+        apimgr.mgr_login()
+        r = apimgr.buyersousuo("万达信息股份有限公司")
+        INFO(r.text)
+        # res =r.json()
+        # buyer_value = res['data']['list'][0]['buyer']
+        STEP(2,'第二步设置检查点')
+        # 设置检查点
+        # CHECK_POINT('检查搜索接口是否正常',res['data']['ckeys'] == 'PH计')
+    #清除方法
+    def teardown(self):
+        INFO('清除方法')

+ 33 - 0
cases/登录功能/搜索功能/enterpriseSearch.py

@@ -0,0 +1,33 @@
+import json
+
+from hytest import *
+from lib.webapi import apimgr
+class c3:
+    #测试用例名称
+    name='企业搜索'
+    # 初始化方法
+    def setup(self):
+        INFO('初始化方法')
+    #测试步骤
+    def teststeps(self):
+        INFO('测试步骤')
+        STEP(1,'第一步调用函数')    #会出现在测试报告中
+        apimgr.mgr_login()
+        r = apimgr.enterpriseSearch()
+        if r is not None:
+            try:
+                res = r.json()
+            except ValueError as e:
+                print(f"Failed to decode JSON response: {e}")
+                res = None
+        else:
+            res = None
+
+        textactual_legal_person = res['data']['list'][0]['legal_person']
+
+        STEP(2,'第二步设置检查点')
+        #设置检查点
+        CHECK_POINT('检查登录接口是否正常',textactual_legal_person == "田小亮")
+    #清除方法
+    def teardown(self):
+        INFO('清除方法')

+ 25 - 0
cases/登录功能/搜索功能/search.py

@@ -0,0 +1,25 @@
+
+from hytest import *
+from lib.webapi import apimgr
+class c2:
+    #测试用例名称
+    name='招标搜索接口'
+    # 初始化方法
+    def setup(self):
+        INFO('初始化方法')
+        self.session = apimgr.mgr_login()
+    #测试步骤
+    def teststeps(self):
+        INFO('测试步骤')
+        STEP(1,'第一步调用函数')    #会出现在测试报告中
+        apimgr.mgr_login()
+        r = apimgr.search()
+        res = r.text
+        keys_value = res.split('var keys = "', 1)[-1].split('"', 1)[0]
+        STEP(2,'第二步设置检查点')
+        #设置检查点
+        CHECK_POINT('检查搜索接口是否正常',keys_value == "建筑")
+    #清除方法
+    def teardown(self):
+        INFO('清除方法')
+        apimgr.mgr_logout(self.session)

+ 26 - 0
cases/登录功能/搜索功能/supplySearch.py

@@ -0,0 +1,26 @@
+import json
+from logging import ERROR
+
+import requests
+from hytest import *
+from lib.webapi import apimgr
+class c4:
+    #测试用例名称
+    name='供应搜索'
+    # 初始化方法
+    def setup(self):
+        INFO('初始化方法')
+    #测试步骤
+    def teststeps(self):
+        INFO('测试步骤')
+        STEP(1,'第一步调用函数')    #会出现在测试报告中
+        apimgr.mgr_login()
+        r = apimgr.supplySearch()
+        # INFO(r.json())
+        res = json.loads(r.content.decode('utf-8'))
+        STEP(2,'第二步设置检查点')
+        #设置检查点
+        CHECK_POINT('检查搜索接口是否正常',res['data']['ckeys'] == 'PH计')
+    #清除方法
+    def teardown(self):
+        INFO('清除方法')

BIN
cases/登录功能/订阅/__pycache__/push_list.cpython-38.pyc


+ 0 - 0
cases/订阅/push_list.py → cases/登录功能/订阅/push_list.py


+ 13 - 5
doc/test.py

@@ -1,4 +1,6 @@
 import requests, json
+from lib.webapi import apimgr
+
 s = requests.Session()
 headers = {
     "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67"
@@ -10,8 +12,14 @@ response = s.post("https://www.jianyu360.cn/phone/login", headers=headers,data=
     'phone': '15225181827',
     'password': '123456'
 })
-r=response.json()
-print(r)
-temp=r['status']
-temp1=r['userInfo']['result']
-print(temp,temp1)
+params = {"keywords": "科技", "publishtime": 'thisyear', "timeslot": "", "area": "", "subtype": "",
+          "minprice": "", "maxprice": "", "industry": "", "buyerclass": "", "buyertel": "", "winnertel": "",
+          "selectType": "title", "notkey": "", "fileExists": "0", "city": "", "searchGroup": "0",
+          "searchMode": "0", "wordsMode": "0", "additionalWords": ""}
+response1 = s.post('https://www.jianyu360.cn/jylab/purSearch/index.html', headers=headers, params=params)
+# r=response1.json()
+apimgr.printResponse(response1)
+print(response1.status_code)
+# temp=r['status']
+# temp1=r['userInfo']['result']
+# print(temp,temp1)

+ 90 - 0
doc/zbsousuo.py

@@ -0,0 +1,90 @@
+import json
+
+import requests
+
+headers1 = {
+    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67"
+}
+
+url = "https://www.jianyu360.cn/phone/login"
+data={
+"reqType": "phoneLogin",
+"isAutoLogin": "false",
+"phone": "18211989987",
+"password": "123456"
+}
+res = requests.post(url=url,headers=headers1,data=data)
+print(res)
+assert res.status_code==200
+assert res.json()["status"] == 1
+assert res.json()["userInfo"]["result"] == "ok"
+assert res.json()["userInfo"]["s_nickname"] == "182****9987"
+cookies=res.cookies
+# print(cookies)
+# print(res.status_code)
+print(res.json())
+cookie_dict = cookies.get_dict()
+session_id = cookie_dict.get("SESSIONID")
+headers = {
+"Content-Type": "application/json",
+"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67",
+    "Cookie": f"SESSIONID={session_id}"
+}
+# print(headers)
+# url = "https://www.jianyu360.cn/jylab/supsearch/index.html"
+# data={
+# "keywords": "建筑",
+# "publishtime": "fiveyear",
+# "selectType": "content"
+# }
+
+# response = requests.post(url=url, headers=headers,data=data)
+# text=response.text
+# print(text)
+# response_text = response.text  # 假设 response 是请求的响应对象,将响应体保存在 response_text 变量中
+
+# 提取 keys 的值
+# keys_value = response_text.split('var keys = "', 1)[-1].split('"', 1)[0]
+
+# 断言 keys 等于 "建筑"
+# assert keys_value == "建筑"
+# url3="https://www.jianyu360.cn/succbi/api/dw/services/queryData"
+# data={"query":
+#           {"resid":"rk6LnRZndKIcnSYLtlpwVG","fields":[{"name":"XMLBDMHZ"}],"sources":"null","filter":[],"params":
+#               [{"name":"searchinput3","value":"科技"}],"sort":[],"options":
+#               {"limit":1,"offset":0,"needResultFilter":"true","queryTotalRowCount":"false"},"queryId":"model6"},
+#                 "resid":"rk6LnRZndKIcnSYLtlpwVG"}
+# rseb=requests.post(url=url,data=data,headers=headers)
+# print(rseb.text)
+# url="https://www.jianyu360.cn/publicapply/enterpriseSearch/doQuery"
+# data={
+# "match": "北京剑鱼信息技术有限公司河南分公司",
+# "matchType": "A",
+# "pageSize": "10",
+# "pageNum": "0"
+# }
+# qq=requests.post(url=url,data=data,headers=headers)
+# print(qq.text)
+
+url2 = "https://www.jianyu360.cn/jyapi/jybx/buyer/eType/buyerList"
+data = {
+    "buyerName": "万达信息股份有限公司",
+    "province": [],
+    "city": [],
+    "buyerClass": [],
+    "isCheckFollow": True,
+    "isCheckReceive": True,
+    "isContact": 0,
+    "pageSize": 10,
+    "pageNum": 1
+}
+
+response = requests.post(url=url2, data=json.dumps(data), headers=headers)
+
+
+print(response.text)
+url3="https://www.jianyu360.cn/jyinfo/supplySearch"
+data={"keywords":"PH计","searchType":"title","province":"","city":"","time":"","status":"0","pageSize":50,"pageIndex":1}
+resa=requests.post(url=url3,headers=headers,data=json.dumps(data))
+res = json.loads(resa.content.decode('utf-8'))
+assert res['data']['ckeys'] == 'PH计'

BIN
lib/__pycache__/webapi.cpython-38.pyc


+ 110 - 4
lib/webapi.py

@@ -32,16 +32,20 @@ class APIMgr():
         print(response.content.decode('utf8'))
         print('----- https response end-----\n\n')
 
+
     headers = {
+
         "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67"
     }
     #headers设置为全局变量
     GSTORE['headers'] = headers
-
+    # session对象设置为全局变量
+    s = requests.Session()
+    GSTORE['s'] = s
     #登录接口
-    def mgr_login(self, phone='15225181827', password='123456',useproxies=False):
+    def mgr_login(self, phone='18211989987', password='123456',useproxies=False):
         headers=GSTORE['headers']
-        self.s = requests.Session()
+        s = GSTORE['s']
         if useproxies:
             self.s.proxies.update({'http':'127.0.0.1:8888'})
         response = self.s.post(f"{cfg.target_host}/phone/login",headers=headers,data=
@@ -54,13 +58,115 @@ class APIMgr():
         self.printResponse(response)
         # 把response对象返回出去
         return response
+
+    def mgr_logout(self):
+        url = f"{cfg.target_host}/front/signOut"
+        headers = GSTORE['headers']
+        s = GSTORE['s']
+        s.post(url=url, headers=headers)
+        # self.printResponse(res)
+        # return res
+
+    def search(self, keywords="建筑", publishtime="fiveyear", selectType="content"):
+        #使用全局变量
+        headers = GSTORE['headers']
+        #保存session
+        session = self.s
+        response = session.post(f"{cfg.target_host}/jylab/supsearch/index.html", headers=headers, data={
+            'keywords': keywords,
+            'publishtime': publishtime,
+            'selectType': selectType
+        })
+        self.printResponse(response)
+        return response
+
+        # 企业搜索
+
+    def enterpriseSearch(self, match="北京剑鱼信息技术有限公司河南分公司", matchType="A", pageSize="10", pageNum="0"):
+        # 使用全局变量
+        headers = GSTORE['headers']
+        # 保存session
+        session = self.s
+        response = session.post(f"{cfg.target_host}/publicapply/enterpriseSearch/doQuery", headers=headers, data={
+            'match': match,
+            'matchType': matchType,
+            'pageSize': pageSize,
+            'pageNum': pageNum
+        })
+        self.printResponse(response)
+        return response
+
+        # 供应搜索
+    def supplySearch(self, keywords="PH计", searchType="title", province="", city="", time="", status="0",
+                         pageSize=50, pageIndex=1):
+        headers = GSTORE['headers']
+        headers['Content-Type'] = 'application/json'  # 添加Content-Type头部
+        url = f"{cfg.target_host}/jyinfo/supplySearch"
+        data = {
+                "keywords": keywords,
+                "searchType": searchType,
+                "province": province,
+                "city": city,
+                "time": time,
+                "status": status,
+                "pageSize": pageSize,
+                "pageIndex": pageIndex
+            }
+        session=self.s
+        response = session.post(url=url, headers=headers, data=json.dumps(data))
+        self.printResponse(response)
+        return response
+
+    #采购单位搜索
+    def buyersousuo(self, buyerName, province=[], city=[], buyerClass=[], isCheckFollow=True, isCheckReceive=True,
+                    isContact=0, pageSize=10,pageNum=1):
+        url = f"{cfg.target_host}/jyapi/jybx/buyer/eType/buyerList"
+        data = {
+            "buyerName": buyerName,
+            "province": province,
+            "city": city,
+            "buyerClass": buyerClass,
+            "isCheckFollow": isCheckFollow,
+            "isCheckReceive": isCheckReceive,
+            "isContact": isContact,
+            "pageSize": pageSize,
+            "pageNum":pageNum
+        }
+        response = requests.post(url=url, data=json.dumps(data), headers=self.headers)
+        self.printResponse(response)
+        return response
+
     #获取推送记录接口
     def push_list(self):
         headers=GSTORE['headers']
+        s = GSTORE['s']
         response = self.s.post(f"{cfg.target_host}/jyapi/jybx/subscribe/fType/list",headers=headers,json=
                          {"pageNum": 1, "pageSize": 50, "format": "table", "area": "", "selectTime": "all", "city": "", "buyerClass": "",
                             "subtype": "", "industry": "", "keyWords": "", "fileExists": "", "price": "", "source": "", "exportNum": "",
                             "vt": ""})
         return  response
 
-apimgr = APIMgr()
+    #不登录招标搜索
+    def notloggedin_search(self, keyword='科技', publishtime='thisyear', selectType='content,title'):
+        headers = GSTORE['headers']
+        params={"keywords": keyword , "publishtime": publishtime, "timeslot": "", "area": "", "subtype": "",
+         "minprice": "", "maxprice": "", "industry": "", "buyerclass": "", "buyertel": "", "winnertel": "",
+         "selectType": selectType, "notkey": "", "fileExists": "0", "city": "", "searchGroup": "0",
+         "searchMode": "0", "wordsMode": "0", "additionalWords": ""}
+        response = requests.post(f"{cfg.target_host}/jylab/supsearch/index.html", headers=headers, params=params)
+        response.raise_for_status()  # 如果请求失败,会抛出异常
+        return response
+
+    #不登录采购单位搜索
+    def notloggedin_buysearch(self,keyword):
+        headers = GSTORE['headers']
+        s = GSTORE['s']
+        data = {"buyerName":keyword,"province":[],"city":[],"buyerClass":[],"isCheckFollow":False,"isCheckReceive":False,"isContact":0,"pageSize":10,"pageNum":1}
+
+        response =s.post(f"{cfg.target_host}/jyapi/jybx/buyer/eType/buyerList", headers=headers, json=data)
+        # response.raise_for_status()  # 如果请求失败,会抛出异常
+        return response
+
+apimgr = APIMgr()
+
+

+ 14 - 21
log/report_20230704_112255.html → log/report_20230706_152619.html

@@ -309,11 +309,11 @@ function next_error(){
             </tr>
             <tr>
               <td>开始时间</td>
-              <td>2023/07/04 11:22:55</td>
+              <td>2023/07/06 15:26:19</td>
             </tr>
             <tr>
               <td>结束时间</td>
-              <td>2023/07/04 11:22:55</td>
+              <td>2023/07/06 15:26:19</td>
             </tr>
             <tr>
               <td>耗时</td>
@@ -392,37 +392,30 @@ function next_error(){
         <h3 style="display:inline">执行日志</h3>
       </div>
       <div class="exec_log">
-        <div class="suite_file" id="suite_file cases/登录功能/login.py">
+        <div class="suite_file" id="suite_file cases/未登录功能/buyersearch.py">
           <div>
             <span class="label">进入文件</span>
-            <span>cases/登录功能/login.py</span>
+            <span>cases/未登录功能/buyersearch.py</span>
           </div>
           <div class="case abort" id="case_00000001">
             <div class="folder_header">
               <span class="label caselabel">用例 ABORT</span>
-              <span class="casename">登录接口验证</span>
-              <span class="executetime">2023-07-04 11:22:55</span>
+              <span class="casename">未登录采购单位搜索</span>
+              <span class="executetime">2023-07-06 15:26:19</span>
             </div>
             <div class="folder_body">
-              <span class="case_class_path">cases/登录功能/login.py::c1</span>
-              <div class="case_setup setup case_st_lable" id="case_setup setup 登录接口验证">
-                <span class="label">用例初始化</span>
-                <div class="info">初始化方法</div>
-              </div>
-              <div class="test_steps" id="test_steps 登录接口验证">
+              <span class="case_class_path">cases/未登录功能/buyersearch.py::c1</span>
+              <div class="test_steps" id="test_steps 未登录采购单位搜索">
                 <span class="label">测试步骤</span>
-                <div class="info">测试步骤</div>
-                <div class="info error-info">STEP() missing 1 required positional argument: 'desc' 
+                <div class="info error-info">'APIMgr' object has no attribute 's' 
 Traceback:
-  File &quot;cases/登录功能/login.py&quot;, line 12, in teststeps
-    STEP('1、第一步')#会出现在测试报告中
-TypeError: STEP() missing 1 required positional argument: 'desc'
+  File &quot;cases/未登录功能/buyersearch.py&quot;, line 7, in teststeps
+    res=apimgr.notloggedin_buysearch('科技')
+  File &quot;/Users/miaobao/Documents/work/autoproject/jianyu_auto_api/lib/webapi.py&quot;, line 187, in notloggedin_buysearch
+    response =self.s.post(f&quot;{cfg.target_host}/jyapi/jybx/buyer/eType/buyerList&quot;, headers=headers, json=data)
+AttributeError: 'APIMgr' object has no attribute 's'
 </div>
               </div>
-              <div class="case_teardown teardown case_st_lable" id="case_teardown teardown 登录接口验证">
-                <span class="label">用例清除</span>
-                <div class="info">清除方法</div>
-              </div>
             </div>
           </div>
         </div>

+ 21 - 15
log/report_20230704_110746.html → log/report_20230706_152740.html

@@ -309,15 +309,15 @@ function next_error(){
             </tr>
             <tr>
               <td>开始时间</td>
-              <td>2023/07/04 11:07:46</td>
+              <td>2023/07/06 15:27:40</td>
             </tr>
             <tr>
               <td>结束时间</td>
-              <td>2023/07/04 11:07:46</td>
+              <td>2023/07/06 15:27:40</td>
             </tr>
             <tr>
               <td>耗时</td>
-              <td>0.010 秒</td>
+              <td>0.003 秒</td>
             </tr>
             <tr>
               <td>预备执行用例数量</td>
@@ -392,34 +392,40 @@ function next_error(){
         <h3 style="display:inline">执行日志</h3>
       </div>
       <div class="exec_log">
-        <div class="suite_file" id="suite_file cases/登录功能/login.py">
+        <div class="suite_file" id="suite_file cases/登录功能/订阅/push_list.py">
           <div>
             <span class="label">进入文件</span>
-            <span>cases/登录功能/login.py</span>
+            <span>cases/登录功能/订阅/push_list.py</span>
           </div>
           <div class="case abort" id="case_00000001">
             <div class="folder_header">
               <span class="label caselabel">用例 ABORT</span>
-              <span class="casename">录接口验证</span>
-              <span class="executetime">2023-07-04 11:07:46</span>
+              <span class="casename">推送记录接口验证</span>
+              <span class="executetime">2023-07-06 15:27:40</span>
             </div>
             <div class="folder_body">
-              <span class="case_class_path">cases/登录功能/login.py::c1</span>
-              <div class="case_setup setup case_st_lable" id="case_setup setup 录接口验证">
+              <span class="case_class_path">cases/登录功能/订阅/push_list.py::c1</span>
+              <div class="case_setup setup case_st_lable" id="case_setup setup 推送记录接口验证">
                 <span class="label">用例初始化</span>
                 <div class="info">初始化方法</div>
               </div>
-              <div class="test_steps" id="test_steps 录接口验证">
+              <div class="test_steps" id="test_steps 推送记录接口验证">
                 <span class="label">测试步骤</span>
                 <div class="info">测试步骤</div>
-                <div class="info error-info">STEP() missing 1 required positional argument: 'desc' 
+                <div class="case_step">
+                  <span class="tag">步骤 #1</span>
+                  <span>第一步调用函数</span>
+                </div>
+                <div class="info error-info">'APIMgr' object has no attribute 's' 
 Traceback:
-  File &quot;cases/登录功能/login.py&quot;, line 12, in teststeps
-    STEP('1、第一步')#会出现在测试报告中
-TypeError: STEP() missing 1 required positional argument: 'desc'
+  File &quot;cases/登录功能/订阅/push_list.py&quot;, line 13, in teststeps
+    r = apimgr.push_list()
+  File &quot;/Users/miaobao/Documents/work/autoproject/jianyu_auto_api/lib/webapi.py&quot;, line 160, in push_list
+    response = self.s.post(f&quot;{cfg.target_host}/jyapi/jybx/subscribe/fType/list&quot;,headers=headers,json=
+AttributeError: 'APIMgr' object has no attribute 's'
 </div>
               </div>
-              <div class="case_teardown teardown case_st_lable" id="case_teardown teardown 录接口验证">
+              <div class="case_teardown teardown case_st_lable" id="case_teardown teardown 推送记录接口验证">
                 <span class="label">用例清除</span>
                 <div class="info">清除方法</div>
               </div>

+ 430 - 0
log/report_20230706_152946.html

@@ -0,0 +1,430 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>测试报告</title>
+    <meta charset="UTF-8">
+    <style>body {    
+    font-family: consolas, Verdana, sans-serif;
+    font-size: .95em;
+    color: #696e71;
+    display: grid;
+    grid-template-columns: 1fr 5rem;
+}
+
+.main_section {   
+    width: 90%;
+    margin: 0 auto;
+}
+
+#float_menu{    
+    position:fixed;
+    top:0;
+    right:0;
+    text-align: center;
+}
+
+#float_menu .menu-item {       
+    cursor: pointer;
+    padding: .5em;
+    margin: .5em 0;
+    color: #c08580;
+    background-color: #f8f0ef;
+    font-size: 1.2em;
+}
+
+
+
+.result{  
+    display: flex;
+}
+  
+  
+.result_table{
+    border-collapse: collapse;
+    border: 1px solid #f0e0e5;
+    width: 30em;
+    text-align: center;
+    font-size: 1.0em;
+}
+      
+.result_table td{
+    border: 1px solid #f0e0e5;
+    padding: .3em;
+}
+  
+.result_barchart{  
+    width: 30em;
+    margin: 0 5em 0 5em;
+}
+  
+.barchar_item{
+    margin: 2.5rem 0;
+}
+  
+.barchart_barbox {
+    margin: 0.5em 0;
+    width: 100%;
+    background-color: #fff;
+    border: 1px solid #86c2dd;
+    border-radius: .2em;
+}
+  
+.barchart_bar {
+    text-align: right;
+    height: 1.2rem;
+}
+  
+  
+
+
+
+.h3_button {
+    margin: 1.5em;
+    cursor: pointer;
+    color: #03a9f4;
+}
+
+
+.info
+{
+    white-space:pre-wrap;
+    margin: .8em 1.5em;
+}
+
+
+.error-info
+{
+    color: #a64747
+}
+
+.suite_dir {
+    margin: 1em .2em;
+    padding: .3em;
+    /* background-color: #dfeff6; */
+    border: 1px solid #bcd8e4;
+}
+.suite_file {
+    margin: 1em .2em;
+    padding: .3em;
+    border: 1px solid #bcd8e4;
+}
+
+
+.case {
+    margin: 1em .2em;
+    /* padding: .3em; */
+    border: 1px solid #e7d4d4;
+}
+
+.case_class_path{
+    margin: 0em 1em; 
+}
+
+
+.folder_header { 
+    padding: .2em .7em;
+    background-color: #fffaf9;
+    cursor: pointer;
+}
+
+
+.setup{
+    margin: .2em;
+    /* padding: .3em; */
+    /* border: 1px solid #e7d4d4; */
+}
+.teardown{
+    margin: .2em;
+    /* padding: .3em;*/
+    /* border: 1px solid #e7d4d4; */
+}
+.test_steps{
+    margin: .2em;
+    padding: .3em;
+    /* border: 1px solid #e7d4d4; */
+}
+
+
+.label {
+    display: inline-block;
+    padding: .1em .5em;
+    font-size: .88em;
+    letter-spacing: 1px;
+    white-space: nowrap;
+    color: #0d6ebc;
+    border-radius: .2em;
+    min-width: 5em;    
+    margin-right: 2em;
+    font-family: consolas;
+}
+
+/* .suite_setup .label{
+    color: #219e26 ;
+}
+.suite_teardown .label{
+    color: #219e26;
+} */
+
+
+/* .case.pass   .casename{
+    color: #329132 ;
+} */
+.case.pass   .caselabel{
+    color: white;
+    background-color: #3b9e3f;
+}
+/* .case.fail   .casename{
+    color: #a64747;
+} */
+.case.fail   .caselabel{
+    color: white;
+    background-color: #a64747;
+}
+/* .case.abort   .casename{
+    color: #953ab7;
+} */
+.case.abort   .caselabel{
+    color: white;
+    background-color: #9c27b0;
+}
+
+
+
+.case_step  {
+    margin: .8em;
+}
+.checkpoint_pass {
+    margin: .8em;
+}
+.checkpoint_fail {
+    margin: .8em;
+}
+
+.case_step  .tag{
+    color: #2196f3;;
+    margin: .3em 1em .3em 0;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+
+.checkpoint_pass .tag{
+    color: #009806;
+    margin:.3em 1em .3em .5em;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+.checkpoint_fail .tag{
+    color: #9c2020;
+    margin:.3em 1em .3em .5em;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+
+.screenshot {
+    border: 1px solid #86c2dd;
+}
+
+.executetime {
+    float: right;
+}</style>
+    <script type="text/javascript">var FOLDER_ALL_CASES = false //是否为精简模式的标记
+var ERROR_INFOS = [];  // 错误信息列表
+var current_error_idx = -1;
+
+// 页面加载后执行的函数
+window.addEventListener("load", function(){
+    // 所有 .folder_header 添加点击事件处理
+    let folderHeaderEles = document.querySelectorAll(".folder_header");
+    folderHeaderEles.forEach(function(ele) {
+        ele.addEventListener("click", function(event) {
+        let fb = event.target.closest('.folder_header').nextElementSibling;
+        fb.style.display = fb.style.display === 'none' ? 'block' : 'none'
+        });
+    });
+
+    // 找到所有的错误信息对象
+    ERROR_INFOS = document.querySelectorAll(".error-info");
+});
+
+
+
+function toggle_folder_all_cases(){
+    let eles = document.querySelectorAll(".folder_body");
+    
+    FOLDER_ALL_CASES = !FOLDER_ALL_CASES;
+    document.getElementById('display_mode').innerHTML = FOLDER_ALL_CASES? "Detail" : "Summary"
+
+    for (const ele of eles){
+        ele.style.display =  FOLDER_ALL_CASES? "none": "block"
+    }
+    
+}
+
+
+
+function previous_error(){
+    // 查找错误必须是详细模式
+    if (FOLDER_ALL_CASES)
+        toggle_folder_all_cases()
+
+    current_error_idx -= 1; 
+    if (current_error_idx<0)
+        current_error_idx = 0
+
+    
+    let error = ERROR_INFOS[current_error_idx];
+
+    error.scrollIntoView({behavior: "smooth", block: "center", inline: "start"});
+
+    
+}
+
+
+function next_error(){
+    
+    // 查找错误必须是详细模式
+    if (FOLDER_ALL_CASES)
+        toggle_folder_all_cases()
+
+    current_error_idx += 1;
+    if (current_error_idx > ERROR_INFOS.length-1)
+        current_error_idx = ERROR_INFOS.length-1
+
+    let error = ERROR_INFOS[current_error_idx];
+
+    error.scrollIntoView({behavior: "smooth", block: "center", inline: "start"});
+    
+}</script>
+  </head>
+  <body>
+    <div class="main_section">
+      <h1 style="font-family: auto">测试报告</h1>
+      <h3>统计结果</h3>
+      <div class="result">
+        <table class="result_table">
+          <tbody>
+            <tr>
+              <td>hytest 版本</td>
+              <td>0.8.11</td>
+            </tr>
+            <tr>
+              <td>开始时间</td>
+              <td>2023/07/06 15:29:46</td>
+            </tr>
+            <tr>
+              <td>结束时间</td>
+              <td>2023/07/06 15:29:46</td>
+            </tr>
+            <tr>
+              <td>耗时</td>
+              <td>0.179 秒</td>
+            </tr>
+            <tr>
+              <td>预备执行用例数量</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>实际执用例行数量</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>通过</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>异常</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>阻塞</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>套件初始化失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>套件清除  失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>用例初始化失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>用例清除  失败</td>
+              <td style="">0</td>
+            </tr>
+          </tbody>
+        </table>
+        <div class="result_barchart">
+          <div class="barchar_item">
+            <span>用例通过 100% : 1 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 100.0%; background-color: #04AA6D;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例失败 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #bb4069;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例异常 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #9c27b0;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例阻塞 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #dcbdbd;"></div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div style="margin-top:2em">
+        <h3 style="display:inline">执行日志</h3>
+      </div>
+      <div class="exec_log">
+        <div class="suite_file" id="suite_file cases/未登录功能/buyersearch.py">
+          <div>
+            <span class="label">进入文件</span>
+            <span>cases/未登录功能/buyersearch.py</span>
+          </div>
+          <div class="case pass" id="case_00000001">
+            <div class="folder_header">
+              <span class="label caselabel">用例 PASS</span>
+              <span class="casename">未登录采购单位搜索</span>
+              <span class="executetime">2023-07-06 15:29:46</span>
+            </div>
+            <div class="folder_body">
+              <span class="case_class_path">cases/未登录功能/buyersearch.py::c1</span>
+              <div class="test_steps" id="test_steps 未登录采购单位搜索">
+                <span class="label">测试步骤</span>
+                <div class="checkpoint_pass">
+                  <span class="tag">检查点 PASS</span>
+                  <span>检查未登录采购单位搜索接口是否正常</span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div id="float_menu">
+      <div class="menu-item" onclick="document.querySelector(&quot;body&quot;).scrollIntoView()">页首</div>
+      <div class="menu-item" onclick="window.open(&quot;http://www.byhy.net/tut/auto/hytest/01&quot;, &quot;_blank&quot;); ">帮助</div>
+      <div class="menu-item" id="display_mode" onclick="toggle_folder_all_cases()">Summary</div>
+      <div class="error_jumper" display="none">
+        <div class="menu-item" onclick="previous_error()" title="上一个错误">∧</div>
+        <div class="menu-item" onclick="next_error()" title="下一个错误">∨</div>
+      </div>
+    </div>
+  </body>
+</html>

+ 19 - 15
log/report_20230704_110913.html → log/report_20230706_153106.html

@@ -309,15 +309,15 @@ function next_error(){
             </tr>
             <tr>
               <td>开始时间</td>
-              <td>2023/07/04 11:09:13</td>
+              <td>2023/07/06 15:31:06</td>
             </tr>
             <tr>
               <td>结束时间</td>
-              <td>2023/07/04 11:09:14</td>
+              <td>2023/07/06 15:31:06</td>
             </tr>
             <tr>
               <td>耗时</td>
-              <td>0.009 秒</td>
+              <td>0.116 秒</td>
             </tr>
             <tr>
               <td>预备执行用例数量</td>
@@ -392,34 +392,38 @@ function next_error(){
         <h3 style="display:inline">执行日志</h3>
       </div>
       <div class="exec_log">
-        <div class="suite_file" id="suite_file cases/登录功能/login.py">
+        <div class="suite_file" id="suite_file cases/登录功能/订阅/push_list.py">
           <div>
             <span class="label">进入文件</span>
-            <span>cases/登录功能/login.py</span>
+            <span>cases/登录功能/订阅/push_list.py</span>
           </div>
           <div class="case abort" id="case_00000001">
             <div class="folder_header">
               <span class="label caselabel">用例 ABORT</span>
-              <span class="casename">录接口验证</span>
-              <span class="executetime">2023-07-04 11:09:13</span>
+              <span class="casename">推送记录接口验证</span>
+              <span class="executetime">2023-07-06 15:31:06</span>
             </div>
             <div class="folder_body">
-              <span class="case_class_path">cases/登录功能/login.py::c1</span>
-              <div class="case_setup setup case_st_lable" id="case_setup setup 录接口验证">
+              <span class="case_class_path">cases/登录功能/订阅/push_list.py::c1</span>
+              <div class="case_setup setup case_st_lable" id="case_setup setup 推送记录接口验证">
                 <span class="label">用例初始化</span>
                 <div class="info">初始化方法</div>
               </div>
-              <div class="test_steps" id="test_steps 录接口验证">
+              <div class="test_steps" id="test_steps 推送记录接口验证">
                 <span class="label">测试步骤</span>
                 <div class="info">测试步骤</div>
-                <div class="info error-info">STEP() missing 1 required positional argument: 'desc' 
+                <div class="case_step">
+                  <span class="tag">步骤 #1</span>
+                  <span>第一步调用函数</span>
+                </div>
+                <div class="info error-info">'data' 
 Traceback:
-  File &quot;cases/登录功能/login.py&quot;, line 12, in teststeps
-    STEP('1、第一步')#会出现在测试报告中
-TypeError: STEP() missing 1 required positional argument: 'desc'
+  File &quot;cases/登录功能/订阅/push_list.py&quot;, line 15, in teststeps
+    actural = res['data']['count']
+KeyError: 'data'
 </div>
               </div>
-              <div class="case_teardown teardown case_st_lable" id="case_teardown teardown 录接口验证">
+              <div class="case_teardown teardown case_st_lable" id="case_teardown teardown 推送记录接口验证">
                 <span class="label">用例清除</span>
                 <div class="info">清除方法</div>
               </div>

+ 15 - 22
log/report_20230704_110820.html → log/report_20230706_153139.html

@@ -309,15 +309,15 @@ function next_error(){
             </tr>
             <tr>
               <td>开始时间</td>
-              <td>2023/07/04 11:08:20</td>
+              <td>2023/07/06 15:31:39</td>
             </tr>
             <tr>
               <td>结束时间</td>
-              <td>2023/07/04 11:08:20</td>
+              <td>2023/07/06 15:31:39</td>
             </tr>
             <tr>
               <td>耗时</td>
-              <td>0.010 秒</td>
+              <td>0.003 秒</td>
             </tr>
             <tr>
               <td>预备执行用例数量</td>
@@ -392,37 +392,30 @@ function next_error(){
         <h3 style="display:inline">执行日志</h3>
       </div>
       <div class="exec_log">
-        <div class="suite_file" id="suite_file cases/登录功能/login.py">
+        <div class="suite_file" id="suite_file cases/未登录功能/buyersearch.py">
           <div>
             <span class="label">进入文件</span>
-            <span>cases/登录功能/login.py</span>
+            <span>cases/未登录功能/buyersearch.py</span>
           </div>
           <div class="case abort" id="case_00000001">
             <div class="folder_header">
               <span class="label caselabel">用例 ABORT</span>
-              <span class="casename">登录接口验证</span>
-              <span class="executetime">2023-07-04 11:08:20</span>
+              <span class="casename">未登录采购单位搜索</span>
+              <span class="executetime">2023-07-06 15:31:39</span>
             </div>
             <div class="folder_body">
-              <span class="case_class_path">cases/登录功能/login.py::c1</span>
-              <div class="case_setup setup case_st_lable" id="case_setup setup 登录接口验证">
-                <span class="label">用例初始化</span>
-                <div class="info">初始化方法</div>
-              </div>
-              <div class="test_steps" id="test_steps 登录接口验证">
+              <span class="case_class_path">cases/未登录功能/buyersearch.py::c1</span>
+              <div class="test_steps" id="test_steps 未登录采购单位搜索">
                 <span class="label">测试步骤</span>
-                <div class="info">测试步骤</div>
-                <div class="info error-info">STEP() missing 1 required positional argument: 'desc' 
+                <div class="info error-info">name 's' is not defined 
 Traceback:
-  File &quot;cases/登录功能/login.py&quot;, line 12, in teststeps
-    STEP('1、第一步')#会出现在测试报告中
-TypeError: STEP() missing 1 required positional argument: 'desc'
+  File &quot;cases/未登录功能/buyersearch.py&quot;, line 7, in teststeps
+    res=apimgr.notloggedin_buysearch('科技')
+  File &quot;/Users/miaobao/Documents/work/autoproject/jianyu_auto_api/lib/webapi.py&quot;, line 189, in notloggedin_buysearch
+    response =s.post(f&quot;{cfg.target_host}/jyapi/jybx/buyer/eType/buyerList&quot;, headers=headers, json=data)
+NameError: name 's' is not defined
 </div>
               </div>
-              <div class="case_teardown teardown case_st_lable" id="case_teardown teardown 登录接口验证">
-                <span class="label">用例清除</span>
-                <div class="info">清除方法</div>
-              </div>
             </div>
           </div>
         </div>

+ 19 - 15
log/report_20230704_110622.html → log/report_20230706_153217.html

@@ -309,15 +309,15 @@ function next_error(){
             </tr>
             <tr>
               <td>开始时间</td>
-              <td>2023/07/04 11:06:22</td>
+              <td>2023/07/06 15:32:17</td>
             </tr>
             <tr>
               <td>结束时间</td>
-              <td>2023/07/04 11:06:22</td>
+              <td>2023/07/06 15:32:17</td>
             </tr>
             <tr>
               <td>耗时</td>
-              <td>0.010 秒</td>
+              <td>0.178 秒</td>
             </tr>
             <tr>
               <td>预备执行用例数量</td>
@@ -392,34 +392,38 @@ function next_error(){
         <h3 style="display:inline">执行日志</h3>
       </div>
       <div class="exec_log">
-        <div class="suite_file" id="suite_file cases/登录功能/login.py">
+        <div class="suite_file" id="suite_file cases/登录功能/订阅/push_list.py">
           <div>
             <span class="label">进入文件</span>
-            <span>cases/登录功能/login.py</span>
+            <span>cases/登录功能/订阅/push_list.py</span>
           </div>
           <div class="case abort" id="case_00000001">
             <div class="folder_header">
               <span class="label caselabel">用例 ABORT</span>
-              <span class="casename">录接口验证</span>
-              <span class="executetime">2023-07-04 11:06:22</span>
+              <span class="casename">推送记录接口验证</span>
+              <span class="executetime">2023-07-06 15:32:17</span>
             </div>
             <div class="folder_body">
-              <span class="case_class_path">cases/登录功能/login.py::c1</span>
-              <div class="case_setup setup case_st_lable" id="case_setup setup 录接口验证">
+              <span class="case_class_path">cases/登录功能/订阅/push_list.py::c1</span>
+              <div class="case_setup setup case_st_lable" id="case_setup setup 推送记录接口验证">
                 <span class="label">用例初始化</span>
                 <div class="info">初始化方法</div>
               </div>
-              <div class="test_steps" id="test_steps 录接口验证">
+              <div class="test_steps" id="test_steps 推送记录接口验证">
                 <span class="label">测试步骤</span>
                 <div class="info">测试步骤</div>
-                <div class="info error-info">STEP() missing 1 required positional argument: 'desc' 
+                <div class="case_step">
+                  <span class="tag">步骤 #1</span>
+                  <span>第一步调用函数</span>
+                </div>
+                <div class="info error-info">'data' 
 Traceback:
-  File &quot;cases/登录功能/login.py&quot;, line 12, in teststeps
-    STEP('1、第一步')#会出现在测试报告中
-TypeError: STEP() missing 1 required positional argument: 'desc'
+  File &quot;cases/登录功能/订阅/push_list.py&quot;, line 15, in teststeps
+    actural = res['data']['count']
+KeyError: 'data'
 </div>
               </div>
-              <div class="case_teardown teardown case_st_lable" id="case_teardown teardown 录接口验证">
+              <div class="case_teardown teardown case_st_lable" id="case_teardown teardown 推送记录接口验证">
                 <span class="label">用例清除</span>
                 <div class="info">清除方法</div>
               </div>

+ 430 - 0
log/report_20230706_155630.html

@@ -0,0 +1,430 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>测试报告</title>
+    <meta charset="UTF-8">
+    <style>body {    
+    font-family: consolas, Verdana, sans-serif;
+    font-size: .95em;
+    color: #696e71;
+    display: grid;
+    grid-template-columns: 1fr 5rem;
+}
+
+.main_section {   
+    width: 90%;
+    margin: 0 auto;
+}
+
+#float_menu{    
+    position:fixed;
+    top:0;
+    right:0;
+    text-align: center;
+}
+
+#float_menu .menu-item {       
+    cursor: pointer;
+    padding: .5em;
+    margin: .5em 0;
+    color: #c08580;
+    background-color: #f8f0ef;
+    font-size: 1.2em;
+}
+
+
+
+.result{  
+    display: flex;
+}
+  
+  
+.result_table{
+    border-collapse: collapse;
+    border: 1px solid #f0e0e5;
+    width: 30em;
+    text-align: center;
+    font-size: 1.0em;
+}
+      
+.result_table td{
+    border: 1px solid #f0e0e5;
+    padding: .3em;
+}
+  
+.result_barchart{  
+    width: 30em;
+    margin: 0 5em 0 5em;
+}
+  
+.barchar_item{
+    margin: 2.5rem 0;
+}
+  
+.barchart_barbox {
+    margin: 0.5em 0;
+    width: 100%;
+    background-color: #fff;
+    border: 1px solid #86c2dd;
+    border-radius: .2em;
+}
+  
+.barchart_bar {
+    text-align: right;
+    height: 1.2rem;
+}
+  
+  
+
+
+
+.h3_button {
+    margin: 1.5em;
+    cursor: pointer;
+    color: #03a9f4;
+}
+
+
+.info
+{
+    white-space:pre-wrap;
+    margin: .8em 1.5em;
+}
+
+
+.error-info
+{
+    color: #a64747
+}
+
+.suite_dir {
+    margin: 1em .2em;
+    padding: .3em;
+    /* background-color: #dfeff6; */
+    border: 1px solid #bcd8e4;
+}
+.suite_file {
+    margin: 1em .2em;
+    padding: .3em;
+    border: 1px solid #bcd8e4;
+}
+
+
+.case {
+    margin: 1em .2em;
+    /* padding: .3em; */
+    border: 1px solid #e7d4d4;
+}
+
+.case_class_path{
+    margin: 0em 1em; 
+}
+
+
+.folder_header { 
+    padding: .2em .7em;
+    background-color: #fffaf9;
+    cursor: pointer;
+}
+
+
+.setup{
+    margin: .2em;
+    /* padding: .3em; */
+    /* border: 1px solid #e7d4d4; */
+}
+.teardown{
+    margin: .2em;
+    /* padding: .3em;*/
+    /* border: 1px solid #e7d4d4; */
+}
+.test_steps{
+    margin: .2em;
+    padding: .3em;
+    /* border: 1px solid #e7d4d4; */
+}
+
+
+.label {
+    display: inline-block;
+    padding: .1em .5em;
+    font-size: .88em;
+    letter-spacing: 1px;
+    white-space: nowrap;
+    color: #0d6ebc;
+    border-radius: .2em;
+    min-width: 5em;    
+    margin-right: 2em;
+    font-family: consolas;
+}
+
+/* .suite_setup .label{
+    color: #219e26 ;
+}
+.suite_teardown .label{
+    color: #219e26;
+} */
+
+
+/* .case.pass   .casename{
+    color: #329132 ;
+} */
+.case.pass   .caselabel{
+    color: white;
+    background-color: #3b9e3f;
+}
+/* .case.fail   .casename{
+    color: #a64747;
+} */
+.case.fail   .caselabel{
+    color: white;
+    background-color: #a64747;
+}
+/* .case.abort   .casename{
+    color: #953ab7;
+} */
+.case.abort   .caselabel{
+    color: white;
+    background-color: #9c27b0;
+}
+
+
+
+.case_step  {
+    margin: .8em;
+}
+.checkpoint_pass {
+    margin: .8em;
+}
+.checkpoint_fail {
+    margin: .8em;
+}
+
+.case_step  .tag{
+    color: #2196f3;;
+    margin: .3em 1em .3em 0;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+
+.checkpoint_pass .tag{
+    color: #009806;
+    margin:.3em 1em .3em .5em;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+.checkpoint_fail .tag{
+    color: #9c2020;
+    margin:.3em 1em .3em .5em;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+
+.screenshot {
+    border: 1px solid #86c2dd;
+}
+
+.executetime {
+    float: right;
+}</style>
+    <script type="text/javascript">var FOLDER_ALL_CASES = false //是否为精简模式的标记
+var ERROR_INFOS = [];  // 错误信息列表
+var current_error_idx = -1;
+
+// 页面加载后执行的函数
+window.addEventListener("load", function(){
+    // 所有 .folder_header 添加点击事件处理
+    let folderHeaderEles = document.querySelectorAll(".folder_header");
+    folderHeaderEles.forEach(function(ele) {
+        ele.addEventListener("click", function(event) {
+        let fb = event.target.closest('.folder_header').nextElementSibling;
+        fb.style.display = fb.style.display === 'none' ? 'block' : 'none'
+        });
+    });
+
+    // 找到所有的错误信息对象
+    ERROR_INFOS = document.querySelectorAll(".error-info");
+});
+
+
+
+function toggle_folder_all_cases(){
+    let eles = document.querySelectorAll(".folder_body");
+    
+    FOLDER_ALL_CASES = !FOLDER_ALL_CASES;
+    document.getElementById('display_mode').innerHTML = FOLDER_ALL_CASES? "Detail" : "Summary"
+
+    for (const ele of eles){
+        ele.style.display =  FOLDER_ALL_CASES? "none": "block"
+    }
+    
+}
+
+
+
+function previous_error(){
+    // 查找错误必须是详细模式
+    if (FOLDER_ALL_CASES)
+        toggle_folder_all_cases()
+
+    current_error_idx -= 1; 
+    if (current_error_idx<0)
+        current_error_idx = 0
+
+    
+    let error = ERROR_INFOS[current_error_idx];
+
+    error.scrollIntoView({behavior: "smooth", block: "center", inline: "start"});
+
+    
+}
+
+
+function next_error(){
+    
+    // 查找错误必须是详细模式
+    if (FOLDER_ALL_CASES)
+        toggle_folder_all_cases()
+
+    current_error_idx += 1;
+    if (current_error_idx > ERROR_INFOS.length-1)
+        current_error_idx = ERROR_INFOS.length-1
+
+    let error = ERROR_INFOS[current_error_idx];
+
+    error.scrollIntoView({behavior: "smooth", block: "center", inline: "start"});
+    
+}</script>
+  </head>
+  <body>
+    <div class="main_section">
+      <h1 style="font-family: auto">测试报告</h1>
+      <h3>统计结果</h3>
+      <div class="result">
+        <table class="result_table">
+          <tbody>
+            <tr>
+              <td>hytest 版本</td>
+              <td>0.8.11</td>
+            </tr>
+            <tr>
+              <td>开始时间</td>
+              <td>2023/07/06 15:56:30</td>
+            </tr>
+            <tr>
+              <td>结束时间</td>
+              <td>2023/07/06 15:56:30</td>
+            </tr>
+            <tr>
+              <td>耗时</td>
+              <td>0.570 秒</td>
+            </tr>
+            <tr>
+              <td>预备执行用例数量</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>实际执用例行数量</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>通过</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>异常</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>阻塞</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>套件初始化失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>套件清除  失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>用例初始化失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>用例清除  失败</td>
+              <td style="">0</td>
+            </tr>
+          </tbody>
+        </table>
+        <div class="result_barchart">
+          <div class="barchar_item">
+            <span>用例通过 100% : 1 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 100.0%; background-color: #04AA6D;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例失败 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #bb4069;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例异常 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #9c27b0;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例阻塞 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #dcbdbd;"></div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div style="margin-top:2em">
+        <h3 style="display:inline">执行日志</h3>
+      </div>
+      <div class="exec_log">
+        <div class="suite_file" id="suite_file cases/未登录功能/bidsearch.py">
+          <div>
+            <span class="label">进入文件</span>
+            <span>cases/未登录功能/bidsearch.py</span>
+          </div>
+          <div class="case pass" id="case_00000001">
+            <div class="folder_header">
+              <span class="label caselabel">用例 PASS</span>
+              <span class="casename">未登录招标搜索</span>
+              <span class="executetime">2023-07-06 15:56:30</span>
+            </div>
+            <div class="folder_body">
+              <span class="case_class_path">cases/未登录功能/bidsearch.py::c1</span>
+              <div class="test_steps" id="test_steps 未登录招标搜索">
+                <span class="label">测试步骤</span>
+                <div class="checkpoint_pass">
+                  <span class="tag">检查点 PASS</span>
+                  <span>检查未登录采购单位搜索接口是否正常</span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div id="float_menu">
+      <div class="menu-item" onclick="document.querySelector(&quot;body&quot;).scrollIntoView()">页首</div>
+      <div class="menu-item" onclick="window.open(&quot;http://www.byhy.net/tut/auto/hytest/01&quot;, &quot;_blank&quot;); ">帮助</div>
+      <div class="menu-item" id="display_mode" onclick="toggle_folder_all_cases()">Summary</div>
+      <div class="error_jumper" display="none">
+        <div class="menu-item" onclick="previous_error()" title="上一个错误">∧</div>
+        <div class="menu-item" onclick="next_error()" title="下一个错误">∨</div>
+      </div>
+    </div>
+  </body>
+</html>

+ 481 - 0
log/report_20230706_160520.html

@@ -0,0 +1,481 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>测试报告</title>
+    <meta charset="UTF-8">
+    <style>body {    
+    font-family: consolas, Verdana, sans-serif;
+    font-size: .95em;
+    color: #696e71;
+    display: grid;
+    grid-template-columns: 1fr 5rem;
+}
+
+.main_section {   
+    width: 90%;
+    margin: 0 auto;
+}
+
+#float_menu{    
+    position:fixed;
+    top:0;
+    right:0;
+    text-align: center;
+}
+
+#float_menu .menu-item {       
+    cursor: pointer;
+    padding: .5em;
+    margin: .5em 0;
+    color: #c08580;
+    background-color: #f8f0ef;
+    font-size: 1.2em;
+}
+
+
+
+.result{  
+    display: flex;
+}
+  
+  
+.result_table{
+    border-collapse: collapse;
+    border: 1px solid #f0e0e5;
+    width: 30em;
+    text-align: center;
+    font-size: 1.0em;
+}
+      
+.result_table td{
+    border: 1px solid #f0e0e5;
+    padding: .3em;
+}
+  
+.result_barchart{  
+    width: 30em;
+    margin: 0 5em 0 5em;
+}
+  
+.barchar_item{
+    margin: 2.5rem 0;
+}
+  
+.barchart_barbox {
+    margin: 0.5em 0;
+    width: 100%;
+    background-color: #fff;
+    border: 1px solid #86c2dd;
+    border-radius: .2em;
+}
+  
+.barchart_bar {
+    text-align: right;
+    height: 1.2rem;
+}
+  
+  
+
+
+
+.h3_button {
+    margin: 1.5em;
+    cursor: pointer;
+    color: #03a9f4;
+}
+
+
+.info
+{
+    white-space:pre-wrap;
+    margin: .8em 1.5em;
+}
+
+
+.error-info
+{
+    color: #a64747
+}
+
+.suite_dir {
+    margin: 1em .2em;
+    padding: .3em;
+    /* background-color: #dfeff6; */
+    border: 1px solid #bcd8e4;
+}
+.suite_file {
+    margin: 1em .2em;
+    padding: .3em;
+    border: 1px solid #bcd8e4;
+}
+
+
+.case {
+    margin: 1em .2em;
+    /* padding: .3em; */
+    border: 1px solid #e7d4d4;
+}
+
+.case_class_path{
+    margin: 0em 1em; 
+}
+
+
+.folder_header { 
+    padding: .2em .7em;
+    background-color: #fffaf9;
+    cursor: pointer;
+}
+
+
+.setup{
+    margin: .2em;
+    /* padding: .3em; */
+    /* border: 1px solid #e7d4d4; */
+}
+.teardown{
+    margin: .2em;
+    /* padding: .3em;*/
+    /* border: 1px solid #e7d4d4; */
+}
+.test_steps{
+    margin: .2em;
+    padding: .3em;
+    /* border: 1px solid #e7d4d4; */
+}
+
+
+.label {
+    display: inline-block;
+    padding: .1em .5em;
+    font-size: .88em;
+    letter-spacing: 1px;
+    white-space: nowrap;
+    color: #0d6ebc;
+    border-radius: .2em;
+    min-width: 5em;    
+    margin-right: 2em;
+    font-family: consolas;
+}
+
+/* .suite_setup .label{
+    color: #219e26 ;
+}
+.suite_teardown .label{
+    color: #219e26;
+} */
+
+
+/* .case.pass   .casename{
+    color: #329132 ;
+} */
+.case.pass   .caselabel{
+    color: white;
+    background-color: #3b9e3f;
+}
+/* .case.fail   .casename{
+    color: #a64747;
+} */
+.case.fail   .caselabel{
+    color: white;
+    background-color: #a64747;
+}
+/* .case.abort   .casename{
+    color: #953ab7;
+} */
+.case.abort   .caselabel{
+    color: white;
+    background-color: #9c27b0;
+}
+
+
+
+.case_step  {
+    margin: .8em;
+}
+.checkpoint_pass {
+    margin: .8em;
+}
+.checkpoint_fail {
+    margin: .8em;
+}
+
+.case_step  .tag{
+    color: #2196f3;;
+    margin: .3em 1em .3em 0;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+
+.checkpoint_pass .tag{
+    color: #009806;
+    margin:.3em 1em .3em .5em;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+.checkpoint_fail .tag{
+    color: #9c2020;
+    margin:.3em 1em .3em .5em;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+
+.screenshot {
+    border: 1px solid #86c2dd;
+}
+
+.executetime {
+    float: right;
+}</style>
+    <script type="text/javascript">var FOLDER_ALL_CASES = false //是否为精简模式的标记
+var ERROR_INFOS = [];  // 错误信息列表
+var current_error_idx = -1;
+
+// 页面加载后执行的函数
+window.addEventListener("load", function(){
+    // 所有 .folder_header 添加点击事件处理
+    let folderHeaderEles = document.querySelectorAll(".folder_header");
+    folderHeaderEles.forEach(function(ele) {
+        ele.addEventListener("click", function(event) {
+        let fb = event.target.closest('.folder_header').nextElementSibling;
+        fb.style.display = fb.style.display === 'none' ? 'block' : 'none'
+        });
+    });
+
+    // 找到所有的错误信息对象
+    ERROR_INFOS = document.querySelectorAll(".error-info");
+});
+
+
+
+function toggle_folder_all_cases(){
+    let eles = document.querySelectorAll(".folder_body");
+    
+    FOLDER_ALL_CASES = !FOLDER_ALL_CASES;
+    document.getElementById('display_mode').innerHTML = FOLDER_ALL_CASES? "Detail" : "Summary"
+
+    for (const ele of eles){
+        ele.style.display =  FOLDER_ALL_CASES? "none": "block"
+    }
+    
+}
+
+
+
+function previous_error(){
+    // 查找错误必须是详细模式
+    if (FOLDER_ALL_CASES)
+        toggle_folder_all_cases()
+
+    current_error_idx -= 1; 
+    if (current_error_idx<0)
+        current_error_idx = 0
+
+    
+    let error = ERROR_INFOS[current_error_idx];
+
+    error.scrollIntoView({behavior: "smooth", block: "center", inline: "start"});
+
+    
+}
+
+
+function next_error(){
+    
+    // 查找错误必须是详细模式
+    if (FOLDER_ALL_CASES)
+        toggle_folder_all_cases()
+
+    current_error_idx += 1;
+    if (current_error_idx > ERROR_INFOS.length-1)
+        current_error_idx = ERROR_INFOS.length-1
+
+    let error = ERROR_INFOS[current_error_idx];
+
+    error.scrollIntoView({behavior: "smooth", block: "center", inline: "start"});
+    
+}</script>
+  </head>
+  <body>
+    <div class="main_section">
+      <h1 style="font-family: auto">测试报告</h1>
+      <h3>统计结果</h3>
+      <div class="result">
+        <table class="result_table">
+          <tbody>
+            <tr>
+              <td>hytest 版本</td>
+              <td>0.8.11</td>
+            </tr>
+            <tr>
+              <td>开始时间</td>
+              <td>2023/07/06 16:05:20</td>
+            </tr>
+            <tr>
+              <td>结束时间</td>
+              <td>2023/07/06 16:05:20</td>
+            </tr>
+            <tr>
+              <td>耗时</td>
+              <td>0.280 秒</td>
+            </tr>
+            <tr>
+              <td>预备执行用例数量</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>实际执用例行数量</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>通过</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>异常</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>阻塞</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>套件初始化失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>套件清除  失败</td>
+              <td style="color:red">1</td>
+            </tr>
+            <tr>
+              <td>用例初始化失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>用例清除  失败</td>
+              <td style="color:red">1</td>
+            </tr>
+          </tbody>
+        </table>
+        <div class="result_barchart">
+          <div class="barchar_item">
+            <span>用例通过 100% : 1 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 100.0%; background-color: #04AA6D;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例失败 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #bb4069;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例异常 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #9c27b0;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例阻塞 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #dcbdbd;"></div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div style="margin-top:2em">
+        <h3 style="display:inline">执行日志</h3>
+      </div>
+      <div class="exec_log">
+        <div class="suite_dir" id="suite_dir cases/登录功能/">
+          <div>
+            <span class="label">进入目录</span>
+            <span>cases/登录功能/</span>
+          </div>
+          <div class="suite_setup setup" id="suite_setup setup cases/登录功能/">
+            <div class="folder_header">
+              <span class="label">套件初始化</span>
+              <span>cases/登录功能/</span>
+              <span class="executetime">2023-07-06 16:05:20</span>
+            </div>
+            <div class="folder_body">
+              <div class="info">用户登录</div>
+            </div>
+          </div>
+        </div>
+        <div class="suite_file" id="suite_file cases/登录功能/login.py">
+          <div>
+            <span class="label">进入文件</span>
+            <span>cases/登录功能/login.py</span>
+          </div>
+          <div class="case pass" id="case_00000001">
+            <div class="folder_header">
+              <span class="label caselabel">用例 PASS</span>
+              <span class="casename">登录接口验证</span>
+              <span class="executetime">2023-07-06 16:05:20</span>
+            </div>
+            <div class="folder_body">
+              <span class="case_class_path">cases/登录功能/login.py::c1</span>
+              <div class="test_steps" id="test_steps 登录接口验证">
+                <span class="label">测试步骤</span>
+                <div class="info">测试步骤</div>
+                <div class="case_step">
+                  <span class="tag">步骤 #1</span>
+                  <span>第一步调用函数</span>
+                </div>
+                <div class="case_step">
+                  <span class="tag">步骤 #2</span>
+                  <span>第二步设置检查点</span>
+                </div>
+                <div class="checkpoint_pass">
+                  <span class="tag">检查点 PASS</span>
+                  <span>检查登录接口是否正常</span>
+                </div>
+              </div>
+              <div class="case_teardown teardown case_st_lable fail" id="case_teardown teardown 登录接口验证">
+                <span class="label">用例清除</span>
+                <div class="info">用户退出</div>
+                <div class="info error-info">case teardown fail | mgr_logout() missing 1 required positional argument: 'session' 
+Traceback:
+  File &quot;cases/登录功能/login.py&quot;, line 20, in teardown
+    apimgr.mgr_logout()
+TypeError: mgr_logout() missing 1 required positional argument: 'session'
+</div>
+              </div>
+            </div>
+          </div>
+          <div class="suite_teardown teardown fail" id="suite_teardown teardown cases/登录功能/">
+            <div class="folder_header">
+              <span class="label">套件清除</span>
+              <span>cases/登录功能/</span>
+              <span class="executetime">2023-07-06 16:05:20</span>
+            </div>
+            <div class="folder_body">
+              <div class="info">用户退出</div>
+              <div class="info error-info">suite teardown fail | mgr_logout() missing 1 required positional argument: 'session' 
+Traceback:
+  File &quot;cases/登录功能/__st__.py&quot;, line 8, in suite_teardown
+    apimgr.mgr_logout()
+TypeError: mgr_logout() missing 1 required positional argument: 'session'
+</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div id="float_menu">
+      <div class="menu-item" onclick="document.querySelector(&quot;body&quot;).scrollIntoView()">页首</div>
+      <div class="menu-item" onclick="window.open(&quot;http://www.byhy.net/tut/auto/hytest/01&quot;, &quot;_blank&quot;); ">帮助</div>
+      <div class="menu-item" id="display_mode" onclick="toggle_folder_all_cases()">Summary</div>
+      <div class="error_jumper" display="block">
+        <div class="menu-item" onclick="previous_error()" title="上一个错误">∧</div>
+        <div class="menu-item" onclick="next_error()" title="下一个错误">∨</div>
+      </div>
+    </div>
+  </body>
+</html>

+ 485 - 0
log/report_20230706_160543.html

@@ -0,0 +1,485 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>测试报告</title>
+    <meta charset="UTF-8">
+    <style>body {    
+    font-family: consolas, Verdana, sans-serif;
+    font-size: .95em;
+    color: #696e71;
+    display: grid;
+    grid-template-columns: 1fr 5rem;
+}
+
+.main_section {   
+    width: 90%;
+    margin: 0 auto;
+}
+
+#float_menu{    
+    position:fixed;
+    top:0;
+    right:0;
+    text-align: center;
+}
+
+#float_menu .menu-item {       
+    cursor: pointer;
+    padding: .5em;
+    margin: .5em 0;
+    color: #c08580;
+    background-color: #f8f0ef;
+    font-size: 1.2em;
+}
+
+
+
+.result{  
+    display: flex;
+}
+  
+  
+.result_table{
+    border-collapse: collapse;
+    border: 1px solid #f0e0e5;
+    width: 30em;
+    text-align: center;
+    font-size: 1.0em;
+}
+      
+.result_table td{
+    border: 1px solid #f0e0e5;
+    padding: .3em;
+}
+  
+.result_barchart{  
+    width: 30em;
+    margin: 0 5em 0 5em;
+}
+  
+.barchar_item{
+    margin: 2.5rem 0;
+}
+  
+.barchart_barbox {
+    margin: 0.5em 0;
+    width: 100%;
+    background-color: #fff;
+    border: 1px solid #86c2dd;
+    border-radius: .2em;
+}
+  
+.barchart_bar {
+    text-align: right;
+    height: 1.2rem;
+}
+  
+  
+
+
+
+.h3_button {
+    margin: 1.5em;
+    cursor: pointer;
+    color: #03a9f4;
+}
+
+
+.info
+{
+    white-space:pre-wrap;
+    margin: .8em 1.5em;
+}
+
+
+.error-info
+{
+    color: #a64747
+}
+
+.suite_dir {
+    margin: 1em .2em;
+    padding: .3em;
+    /* background-color: #dfeff6; */
+    border: 1px solid #bcd8e4;
+}
+.suite_file {
+    margin: 1em .2em;
+    padding: .3em;
+    border: 1px solid #bcd8e4;
+}
+
+
+.case {
+    margin: 1em .2em;
+    /* padding: .3em; */
+    border: 1px solid #e7d4d4;
+}
+
+.case_class_path{
+    margin: 0em 1em; 
+}
+
+
+.folder_header { 
+    padding: .2em .7em;
+    background-color: #fffaf9;
+    cursor: pointer;
+}
+
+
+.setup{
+    margin: .2em;
+    /* padding: .3em; */
+    /* border: 1px solid #e7d4d4; */
+}
+.teardown{
+    margin: .2em;
+    /* padding: .3em;*/
+    /* border: 1px solid #e7d4d4; */
+}
+.test_steps{
+    margin: .2em;
+    padding: .3em;
+    /* border: 1px solid #e7d4d4; */
+}
+
+
+.label {
+    display: inline-block;
+    padding: .1em .5em;
+    font-size: .88em;
+    letter-spacing: 1px;
+    white-space: nowrap;
+    color: #0d6ebc;
+    border-radius: .2em;
+    min-width: 5em;    
+    margin-right: 2em;
+    font-family: consolas;
+}
+
+/* .suite_setup .label{
+    color: #219e26 ;
+}
+.suite_teardown .label{
+    color: #219e26;
+} */
+
+
+/* .case.pass   .casename{
+    color: #329132 ;
+} */
+.case.pass   .caselabel{
+    color: white;
+    background-color: #3b9e3f;
+}
+/* .case.fail   .casename{
+    color: #a64747;
+} */
+.case.fail   .caselabel{
+    color: white;
+    background-color: #a64747;
+}
+/* .case.abort   .casename{
+    color: #953ab7;
+} */
+.case.abort   .caselabel{
+    color: white;
+    background-color: #9c27b0;
+}
+
+
+
+.case_step  {
+    margin: .8em;
+}
+.checkpoint_pass {
+    margin: .8em;
+}
+.checkpoint_fail {
+    margin: .8em;
+}
+
+.case_step  .tag{
+    color: #2196f3;;
+    margin: .3em 1em .3em 0;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+
+.checkpoint_pass .tag{
+    color: #009806;
+    margin:.3em 1em .3em .5em;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+.checkpoint_fail .tag{
+    color: #9c2020;
+    margin:.3em 1em .3em .5em;
+    padding: .1em .3em;
+    font-size: .92em;
+}
+
+.screenshot {
+    border: 1px solid #86c2dd;
+}
+
+.executetime {
+    float: right;
+}</style>
+    <script type="text/javascript">var FOLDER_ALL_CASES = false //是否为精简模式的标记
+var ERROR_INFOS = [];  // 错误信息列表
+var current_error_idx = -1;
+
+// 页面加载后执行的函数
+window.addEventListener("load", function(){
+    // 所有 .folder_header 添加点击事件处理
+    let folderHeaderEles = document.querySelectorAll(".folder_header");
+    folderHeaderEles.forEach(function(ele) {
+        ele.addEventListener("click", function(event) {
+        let fb = event.target.closest('.folder_header').nextElementSibling;
+        fb.style.display = fb.style.display === 'none' ? 'block' : 'none'
+        });
+    });
+
+    // 找到所有的错误信息对象
+    ERROR_INFOS = document.querySelectorAll(".error-info");
+});
+
+
+
+function toggle_folder_all_cases(){
+    let eles = document.querySelectorAll(".folder_body");
+    
+    FOLDER_ALL_CASES = !FOLDER_ALL_CASES;
+    document.getElementById('display_mode').innerHTML = FOLDER_ALL_CASES? "Detail" : "Summary"
+
+    for (const ele of eles){
+        ele.style.display =  FOLDER_ALL_CASES? "none": "block"
+    }
+    
+}
+
+
+
+function previous_error(){
+    // 查找错误必须是详细模式
+    if (FOLDER_ALL_CASES)
+        toggle_folder_all_cases()
+
+    current_error_idx -= 1; 
+    if (current_error_idx<0)
+        current_error_idx = 0
+
+    
+    let error = ERROR_INFOS[current_error_idx];
+
+    error.scrollIntoView({behavior: "smooth", block: "center", inline: "start"});
+
+    
+}
+
+
+function next_error(){
+    
+    // 查找错误必须是详细模式
+    if (FOLDER_ALL_CASES)
+        toggle_folder_all_cases()
+
+    current_error_idx += 1;
+    if (current_error_idx > ERROR_INFOS.length-1)
+        current_error_idx = ERROR_INFOS.length-1
+
+    let error = ERROR_INFOS[current_error_idx];
+
+    error.scrollIntoView({behavior: "smooth", block: "center", inline: "start"});
+    
+}</script>
+  </head>
+  <body>
+    <div class="main_section">
+      <h1 style="font-family: auto">测试报告</h1>
+      <h3>统计结果</h3>
+      <div class="result">
+        <table class="result_table">
+          <tbody>
+            <tr>
+              <td>hytest 版本</td>
+              <td>0.8.11</td>
+            </tr>
+            <tr>
+              <td>开始时间</td>
+              <td>2023/07/06 16:05:43</td>
+            </tr>
+            <tr>
+              <td>结束时间</td>
+              <td>2023/07/06 16:05:44</td>
+            </tr>
+            <tr>
+              <td>耗时</td>
+              <td>0.307 秒</td>
+            </tr>
+            <tr>
+              <td>预备执行用例数量</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>实际执用例行数量</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>通过</td>
+              <td>1</td>
+            </tr>
+            <tr>
+              <td>失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>异常</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>阻塞</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>套件初始化失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>套件清除  失败</td>
+              <td style="color:red">1</td>
+            </tr>
+            <tr>
+              <td>用例初始化失败</td>
+              <td style="">0</td>
+            </tr>
+            <tr>
+              <td>用例清除  失败</td>
+              <td style="color:red">1</td>
+            </tr>
+          </tbody>
+        </table>
+        <div class="result_barchart">
+          <div class="barchar_item">
+            <span>用例通过 100% : 1 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 100.0%; background-color: #04AA6D;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例失败 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #bb4069;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例异常 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #9c27b0;"></div>
+            </div>
+          </div>
+          <div class="barchar_item">
+            <span>用例阻塞 0% : 0 个</span>
+            <div class="barchart_barbox">
+              <div class="barchart_bar" style="width: 0.0%; background-color: #dcbdbd;"></div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div style="margin-top:2em">
+        <h3 style="display:inline">执行日志</h3>
+      </div>
+      <div class="exec_log">
+        <div class="suite_dir" id="suite_dir cases/登录功能/">
+          <div>
+            <span class="label">进入目录</span>
+            <span>cases/登录功能/</span>
+          </div>
+          <div class="suite_setup setup" id="suite_setup setup cases/登录功能/">
+            <div class="folder_header">
+              <span class="label">套件初始化</span>
+              <span>cases/登录功能/</span>
+              <span class="executetime">2023-07-06 16:05:43</span>
+            </div>
+            <div class="folder_body">
+              <div class="info">用户登录</div>
+            </div>
+          </div>
+        </div>
+        <div class="suite_file" id="suite_file cases/登录功能/login.py">
+          <div>
+            <span class="label">进入文件</span>
+            <span>cases/登录功能/login.py</span>
+          </div>
+          <div class="case pass" id="case_00000001">
+            <div class="folder_header">
+              <span class="label caselabel">用例 PASS</span>
+              <span class="casename">登录接口验证</span>
+              <span class="executetime">2023-07-06 16:05:44</span>
+            </div>
+            <div class="folder_body">
+              <span class="case_class_path">cases/登录功能/login.py::c1</span>
+              <div class="test_steps" id="test_steps 登录接口验证">
+                <span class="label">测试步骤</span>
+                <div class="info">测试步骤</div>
+                <div class="case_step">
+                  <span class="tag">步骤 #1</span>
+                  <span>第一步调用函数</span>
+                </div>
+                <div class="case_step">
+                  <span class="tag">步骤 #2</span>
+                  <span>第二步设置检查点</span>
+                </div>
+                <div class="checkpoint_pass">
+                  <span class="tag">检查点 PASS</span>
+                  <span>检查登录接口是否正常</span>
+                </div>
+              </div>
+              <div class="case_teardown teardown case_st_lable fail" id="case_teardown teardown 登录接口验证">
+                <span class="label">用例清除</span>
+                <div class="info">用户退出</div>
+                <div class="info error-info">case teardown fail | name 'session' is not defined 
+Traceback:
+  File &quot;cases/登录功能/login.py&quot;, line 20, in teardown
+    apimgr.mgr_logout()
+  File &quot;/Users/miaobao/Documents/work/autoproject/jianyu_auto_api/lib/webapi.py&quot;, line 82, in mgr_logout
+    session.post(url=url, headers=headers)
+NameError: name 'session' is not defined
+</div>
+              </div>
+            </div>
+          </div>
+          <div class="suite_teardown teardown fail" id="suite_teardown teardown cases/登录功能/">
+            <div class="folder_header">
+              <span class="label">套件清除</span>
+              <span>cases/登录功能/</span>
+              <span class="executetime">2023-07-06 16:05:44</span>
+            </div>
+            <div class="folder_body">
+              <div class="info">用户退出</div>
+              <div class="info error-info">suite teardown fail | name 'session' is not defined 
+Traceback:
+  File &quot;cases/登录功能/__st__.py&quot;, line 8, in suite_teardown
+    apimgr.mgr_logout()
+  File &quot;/Users/miaobao/Documents/work/autoproject/jianyu_auto_api/lib/webapi.py&quot;, line 82, in mgr_logout
+    session.post(url=url, headers=headers)
+NameError: name 'session' is not defined
+</div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div id="float_menu">
+      <div class="menu-item" onclick="document.querySelector(&quot;body&quot;).scrollIntoView()">页首</div>
+      <div class="menu-item" onclick="window.open(&quot;http://www.byhy.net/tut/auto/hytest/01&quot;, &quot;_blank&quot;); ">帮助</div>
+      <div class="menu-item" id="display_mode" onclick="toggle_folder_all_cases()">Summary</div>
+      <div class="error_jumper" display="block">
+        <div class="menu-item" onclick="previous_error()" title="上一个错误">∧</div>
+        <div class="menu-item" onclick="next_error()" title="下一个错误">∨</div>
+      </div>
+    </div>
+  </body>
+</html>

+ 31 - 9
log/report_20230704_132714.html → log/report_20230706_160626.html

@@ -309,15 +309,15 @@ function next_error(){
             </tr>
             <tr>
               <td>开始时间</td>
-              <td>2023/07/04 13:27:14</td>
+              <td>2023/07/06 16:06:26</td>
             </tr>
             <tr>
               <td>结束时间</td>
-              <td>2023/07/04 13:27:14</td>
+              <td>2023/07/06 16:06:27</td>
             </tr>
             <tr>
               <td>耗时</td>
-              <td>0.180 秒</td>
+              <td>0.373 秒</td>
             </tr>
             <tr>
               <td>预备执行用例数量</td>
@@ -392,6 +392,22 @@ function next_error(){
         <h3 style="display:inline">执行日志</h3>
       </div>
       <div class="exec_log">
+        <div class="suite_dir" id="suite_dir cases/登录功能/">
+          <div>
+            <span class="label">进入目录</span>
+            <span>cases/登录功能/</span>
+          </div>
+          <div class="suite_setup setup" id="suite_setup setup cases/登录功能/">
+            <div class="folder_header">
+              <span class="label">套件初始化</span>
+              <span>cases/登录功能/</span>
+              <span class="executetime">2023-07-06 16:06:26</span>
+            </div>
+            <div class="folder_body">
+              <div class="info">用户登录</div>
+            </div>
+          </div>
+        </div>
         <div class="suite_file" id="suite_file cases/登录功能/login.py">
           <div>
             <span class="label">进入文件</span>
@@ -401,14 +417,10 @@ function next_error(){
             <div class="folder_header">
               <span class="label caselabel">用例 PASS</span>
               <span class="casename">登录接口验证</span>
-              <span class="executetime">2023-07-04 13:27:14</span>
+              <span class="executetime">2023-07-06 16:06:26</span>
             </div>
             <div class="folder_body">
               <span class="case_class_path">cases/登录功能/login.py::c1</span>
-              <div class="case_setup setup case_st_lable" id="case_setup setup 登录接口验证">
-                <span class="label">用例初始化</span>
-                <div class="info">初始化方法</div>
-              </div>
               <div class="test_steps" id="test_steps 登录接口验证">
                 <span class="label">测试步骤</span>
                 <div class="info">测试步骤</div>
@@ -427,10 +439,20 @@ function next_error(){
               </div>
               <div class="case_teardown teardown case_st_lable" id="case_teardown teardown 登录接口验证">
                 <span class="label">用例清除</span>
-                <div class="info">清除方法</div>
+                <div class="info">用户退出</div>
               </div>
             </div>
           </div>
+          <div class="suite_teardown teardown" id="suite_teardown teardown cases/登录功能/">
+            <div class="folder_header">
+              <span class="label">套件清除</span>
+              <span>cases/登录功能/</span>
+              <span class="executetime">2023-07-06 16:06:27</span>
+            </div>
+            <div class="folder_body">
+              <div class="info">用户退出</div>
+            </div>
+          </div>
         </div>
       </div>
     </div>

+ 62 - 8
log/testresult.log

@@ -3,9 +3,57 @@
 ===   [ 收集测试用例 ]  === 
 
 
+== cases/未登录功能/buyersearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/未登录功能/bidsearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/__st__.py 
+
+
 == cases/登录功能/login.py 
 
 
+== cases/登录功能/搜索功能/budenglusu.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/buyersearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/budenglubuyer.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/search.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/enterpriseSearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/supplySearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/订阅/push_list.py 
+
+
+** no cases in this file , skip it.
+
 
 ===   [ 执行测试用例 ]  === 
 
@@ -13,16 +61,19 @@
 
 
 
-  ========= 测试开始 : 20230704_132714 =========
+  ========= 测试开始 : 20230706_160626 =========
 
 
 
->>> cases/登录功能/login.py
+>>> cases/登录功能/
 
-* 登录接口验证  -  2023-07-04 13:27:14
+[ suite setup ] cases/登录功能/
+用户登录
 
-[ case setup ] 登录接口验证
-初始化方法
+
+>>> cases/登录功能/login.py
+
+* 登录接口验证  -  2023-07-06 16:06:26
 
   [ case execution steps ]
 测试步骤
@@ -38,13 +89,16 @@
   PASS 
 
 [ case teardown ] 登录接口验证
-清除方法
+用户退出
+
+[ suite teardown ] cases/登录功能/
+用户退出
 
 
-  ========= 测试结束 : 20230704_132714 =========
+  ========= 测试结束 : 20230706_160627 =========
 
 
-  耗时    : 0.180
+  耗时    : 0.373
 
 
   预备执行用例数量 : 1

+ 111 - 6
log/testresult.log.1

@@ -3,9 +3,57 @@
 ===   [ 收集测试用例 ]  === 
 
 
+== cases/未登录功能/buyersearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/未登录功能/bidsearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/__st__.py 
+
+
 == cases/登录功能/login.py 
 
 
+== cases/登录功能/搜索功能/budenglusu.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/buyersearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/budenglubuyer.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/search.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/enterpriseSearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/supplySearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/订阅/push_list.py 
+
+
+** no cases in this file , skip it.
+
 
 ===   [ 执行测试用例 ]  === 
 
@@ -13,19 +61,76 @@
 
 
 
-  ========= 测试开始 : 20230704_113445 =========
+  ========= 测试开始 : 20230706_160543 =========
 
 
 
->>> cases/登录功能/login.py
+>>> cases/登录功能/
 
-* 登录接口验证  -  2023-07-04 11:34:45
+[ suite setup ] cases/登录功能/
+用户登录
 
-[ case setup ] 登录接口验证
-初始化方法
+
+>>> cases/登录功能/login.py
+
+* 登录接口验证  -  2023-07-06 16:05:44
 
   [ case execution steps ]
 测试步骤
 
--- 第 1 步 -- 第一步 
+-- 第 1 步 -- 第一步调用函数 
+
+
+-- 第 2 步 -- 第二步设置检查点 
+
+
+** 检查点 **  检查登录接口是否正常 ---->  通过
+
+  PASS 
+
+[ case teardown ] 登录接口验证
+用户退出
+case teardown fail | name 'session' is not defined 
+Traceback:
+  File "cases/登录功能/login.py", line 20, in teardown
+    apimgr.mgr_logout()
+  File "/Users/miaobao/Documents/work/autoproject/jianyu_auto_api/lib/webapi.py", line 82, in mgr_logout
+    session.post(url=url, headers=headers)
+NameError: name 'session' is not defined
+
+
+[ suite teardown ] cases/登录功能/
+用户退出
+suite teardown fail | name 'session' is not defined 
+Traceback:
+  File "cases/登录功能/__st__.py", line 8, in suite_teardown
+    apimgr.mgr_logout()
+  File "/Users/miaobao/Documents/work/autoproject/jianyu_auto_api/lib/webapi.py", line 82, in mgr_logout
+    session.post(url=url, headers=headers)
+NameError: name 'session' is not defined
+
+
+
+  ========= 测试结束 : 20230706_160544 =========
+
+
+  耗时    : 0.307 秒
+
+
+  预备执行用例数量 : 1
+
+  实际执行用例数量 : 1
+
+  通过 : 1
+
+  失败 : 0
+
+  异常 : 0
+
+  套件初始化失败 : 0
+
+  套件清除  失败 : 1
+
+  用例初始化失败 : 0
 
+  用例清除  失败 : 1

+ 107 - 6
log/testresult.log.2

@@ -3,9 +3,57 @@
 ===   [ 收集测试用例 ]  === 
 
 
+== cases/未登录功能/buyersearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/未登录功能/bidsearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/__st__.py 
+
+
 == cases/登录功能/login.py 
 
 
+== cases/登录功能/搜索功能/budenglusu.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/buyersearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/budenglubuyer.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/search.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/enterpriseSearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/搜索功能/supplySearch.py 
+
+
+** no cases in this file , skip it.
+
+== cases/登录功能/订阅/push_list.py 
+
+
+** no cases in this file , skip it.
+
 
 ===   [ 执行测试用例 ]  === 
 
@@ -13,19 +61,72 @@
 
 
 
-  ========= 测试开始 : 20230704_113101 =========
+  ========= 测试开始 : 20230706_160520 =========
 
 
 
->>> cases/登录功能/login.py
+>>> cases/登录功能/
 
-* 登录接口验证  -  2023-07-04 11:31:01
+[ suite setup ] cases/登录功能/
+用户登录
 
-[ case setup ] 登录接口验证
-初始化方法
+
+>>> cases/登录功能/login.py
+
+* 登录接口验证  -  2023-07-06 16:05:20
 
   [ case execution steps ]
 测试步骤
 
--- 第 1 步 -- 第一步 
+-- 第 1 步 -- 第一步调用函数 
+
+
+-- 第 2 步 -- 第二步设置检查点 
+
+
+** 检查点 **  检查登录接口是否正常 ---->  通过
+
+  PASS 
+
+[ case teardown ] 登录接口验证
+用户退出
+case teardown fail | mgr_logout() missing 1 required positional argument: 'session' 
+Traceback:
+  File "cases/登录功能/login.py", line 20, in teardown
+    apimgr.mgr_logout()
+TypeError: mgr_logout() missing 1 required positional argument: 'session'
+
+
+[ suite teardown ] cases/登录功能/
+用户退出
+suite teardown fail | mgr_logout() missing 1 required positional argument: 'session' 
+Traceback:
+  File "cases/登录功能/__st__.py", line 8, in suite_teardown
+    apimgr.mgr_logout()
+TypeError: mgr_logout() missing 1 required positional argument: 'session'
+
+
+
+  ========= 测试结束 : 20230706_160520 =========
+
+
+  耗时    : 0.280 秒
+
+
+  预备执行用例数量 : 1
+
+  实际执行用例数量 : 1
+
+  通过 : 1
+
+  失败 : 0
+
+  异常 : 0
+
+  套件初始化失败 : 0
+
+  套件清除  失败 : 1
+
+  用例初始化失败 : 0
 
+  用例清除  失败 : 1