├── comm ├── script │ ├── __init__.py │ ├── writeLogs.py │ └── writeCase.py ├── unit │ ├── __init__.py │ ├── readRelevance.py │ ├── queryDatabase.py │ ├── initializePremise.py │ ├── apiSend.py │ └── replaceRelevance.py ├── __init__.py ├── utils │ ├── __init__.py │ ├── readJson.py │ ├── readYaml.py │ ├── readConf.py │ └── randomly.py └── db │ ├── __init__.py │ ├── queryRedis.py │ ├── queryHBase.py │ ├── querySolr.py │ ├── queryMysql.py │ └── queryES.py ├── logs ├── 2021-02-04_error.log └── 2021-02-04.log ├── .gitignore ├── PyDemo ├── report │ ├── html │ │ ├── widgets │ │ │ ├── launch.json │ │ │ ├── environment.json │ │ │ ├── executors.json │ │ │ ├── duration-trend.json │ │ │ ├── categories-trend.json │ │ │ ├── retry-trend.json │ │ │ ├── history-trend.json │ │ │ ├── behaviors.json │ │ │ ├── categories.json │ │ │ ├── suites.json │ │ │ ├── summary.json │ │ │ ├── duration.json │ │ │ ├── severity.json │ │ │ └── status-chart.json │ │ ├── data │ │ │ ├── attachments │ │ │ │ ├── a10e5441521817af.attach │ │ │ │ ├── a142325f6ec7dd97.attach │ │ │ │ ├── a404884c53f9a95e.attach │ │ │ │ ├── b5dbaecb2dacdb90.attach │ │ │ │ ├── d57f284c2a250050.attach │ │ │ │ ├── e5cdc98bcb63fce1.attach │ │ │ │ ├── e645f31e66475871.attach │ │ │ │ ├── f658b4378482d4a.attach │ │ │ │ ├── de7b006637c1f824.attach │ │ │ │ ├── 64929705a353786a.attach │ │ │ │ ├── d4cfa82e3954b068.attach │ │ │ │ ├── 3f3d3b675f8b38f0.attach │ │ │ │ ├── aa3749b1bd00dd8e.attach │ │ │ │ ├── 6d6990d6bc7da779.attach │ │ │ │ ├── 47e7333bf43a045.attach │ │ │ │ ├── ea0ced6a1ef79518.attach │ │ │ │ ├── 436a2d6b50675cb6.attach │ │ │ │ ├── 4ac290f03a0b29ab.attach │ │ │ │ ├── 10ea6ae95941448c.attach │ │ │ │ ├── 45bb27deeb34ae52.attach │ │ │ │ ├── 48d8349a567cd920.attach │ │ │ │ ├── 7f88a98d6e750e3c.attach │ │ │ │ ├── d8d657fe62f789ca.attach │ │ │ │ ├── 9c97dfe6f36b3570.attach │ │ │ │ ├── 5627e81e1f308560.attach │ │ │ │ ├── a2493f73f5b55797.attach │ │ │ │ ├── 7a7457e66b250a1f.attach │ │ │ │ ├── 640913aa912828ba.attach │ │ │ │ ├── b2611d9bc9f7e7f2.attach │ │ │ │ ├── bdc87a179c292ab3.attach │ │ │ │ ├── d7e1801c64f284ab.attach │ │ │ │ ├── 64a95aad22c4bff3.txt │ │ │ │ ├── 1dd259f7ca780bf0.attach │ │ │ │ ├── 4874af030f961a0.attach │ │ │ │ └── e100c861d9156d57.attach │ │ │ ├── categories.csv │ │ │ ├── behaviors.csv │ │ │ ├── suites.csv │ │ │ ├── categories.json │ │ │ ├── timeline.json │ │ │ ├── behaviors.json │ │ │ ├── packages.json │ │ │ ├── suites.json │ │ │ └── test-cases │ │ │ │ ├── aa8dfcaa510813c2.json │ │ │ │ ├── 10d4bd6301177f6.json │ │ │ │ └── 7d4ed4f7a18b20d4.json │ │ ├── favicon.ico │ │ ├── history │ │ │ ├── duration-trend.json │ │ │ ├── categories-trend.json │ │ │ ├── retry-trend.json │ │ │ ├── history-trend.json │ │ │ └── history.json │ │ ├── export │ │ │ ├── mail.html │ │ │ ├── prometheusData.txt │ │ │ └── influxDbData.txt │ │ ├── plugins │ │ │ ├── screen-diff │ │ │ │ ├── styles.css │ │ │ │ └── index.js │ │ │ ├── packages │ │ │ │ └── index.js │ │ │ └── behaviors │ │ │ │ └── index.js │ │ └── index.html │ └── xml │ │ ├── 13581612-dbff-44e2-b614-28aeaf763e53-attachment.attach │ │ ├── 15a5ed09-71be-4302-8da3-f1a3833890c3-attachment.attach │ │ ├── 2d3cbb34-52fb-4b35-80e8-179d043a1226-attachment.attach │ │ ├── 30403406-d497-4fa4-8a90-e52a5f1723aa-attachment.attach │ │ ├── 33849d22-c42b-4fd4-b486-acfe3922e91a-attachment.attach │ │ ├── a925524d-3c79-42dc-a506-ac9353b81a89-attachment.attach │ │ ├── c5f832b3-c5da-4106-8a5d-8bc617600550-attachment.attach │ │ ├── eb8ba490-0f39-42ba-9a1c-44e5ee2a0636-attachment.attach │ │ ├── 9487b1b8-64e5-49d0-a0ea-f2254a0a983f-attachment.attach │ │ ├── 8a751566-67d8-4a28-943a-a0c8cecc3a9f-attachment.attach │ │ ├── b6a76b88-e182-454b-ba36-1e34a5c19222-attachment.attach │ │ ├── da39ce35-693c-4f48-92cd-7795dd783e88-attachment.attach │ │ ├── f1dc7f0e-4445-425a-b4b7-f4b073d49233-attachment.attach │ │ ├── d354f47a-3693-4b7b-86df-cd34ace4ac9c-attachment.attach │ │ ├── 194b21ff-bc74-4712-9e00-2d4d10c529f3-attachment.attach │ │ ├── a6f8bf5f-a42a-4c47-a026-243375a5685d-attachment.attach │ │ ├── 848e4b5e-7e91-4f72-874b-659053c3e48d-attachment.attach │ │ ├── e9a38fd0-5f1b-4739-a472-7606737e0911-attachment.attach │ │ ├── 067d3035-4727-4009-af05-75776743f64e-attachment.attach │ │ ├── 4f67b9c3-4ae0-4945-9697-c30b6dbbcbf0-attachment.attach │ │ ├── 7c22884c-0191-4937-b2d2-12214a869f4c-attachment.attach │ │ ├── d3f438ee-fde7-483c-9a1b-87ce48d23359-attachment.attach │ │ ├── f8618d25-7423-4d9f-a777-b1bc37ee3fd5-attachment.attach │ │ ├── 5f34e443-5ec3-41cf-9002-dd92ec056d54-attachment.attach │ │ ├── 6bc3acef-572c-47fe-9093-56a69faa51ed-attachment.attach │ │ ├── bc8c8933-6042-4cfe-a825-a19018c34101-attachment.attach │ │ ├── aa05cb30-25c4-4485-b7f9-1aa4fd98e692-attachment.attach │ │ ├── 0d998249-b346-4cb4-a883-985eb7fbd7a1-attachment.attach │ │ ├── 31d021db-66cf-4b6c-ae71-15a2e9953294-attachment.attach │ │ ├── b3aaf70f-749f-450d-841f-18feaa49b10d-attachment.attach │ │ ├── 0e77bd92-752b-4668-8685-730d4b4ba05e-container.json │ │ ├── 43aa29f7-e92a-473a-9685-6493d9d40c73-container.json │ │ ├── 5e3fe95f-3c33-4fda-a519-023a25d338d0-container.json │ │ ├── 73339d77-d5f7-4597-8f86-0c8d4816a64e-container.json │ │ ├── ae13f7d4-0fd7-42fd-b524-ac0e2af5718a-attachment.attach │ │ ├── d1e7014d-1938-42c6-a229-2aa35065f3f6-attachment.txt │ │ ├── 21ed8173-cd5d-4d38-95f1-29ba7ef35c26-result.json │ │ ├── 63c03902-4149-4b77-8334-25a617516bde-result.json │ │ ├── dae24e92-696a-4d8a-a4a1-d453299da76d-result.json │ │ ├── 11f08016-1abb-461e-9e6d-fe83310ea63b-attachment.attach │ │ ├── dfe15ef8-3724-4710-b687-fd5f753f0ef0-result.json │ │ ├── a8105e8d-2465-4d01-9dca-cec2937a0cfd-attachment.attach │ │ └── c56c0537-21bd-4b7d-b0d8-6235c48804d2-attachment.attach ├── page │ ├── register │ │ ├── test_initCanSelInfo.yaml │ │ ├── test_addOrUpCurBact.yaml │ │ ├── test_getAdultCurbactList.yaml │ │ ├── test_findParam.yaml │ │ ├── initCanSelInfo_request.json │ │ └── addOrUpCurBact_request.json │ └── perRelated │ │ ├── addAudltCard_request.json │ │ ├── test_addAudltCard.yaml │ │ └── addAudltCard_response.json ├── testcase │ ├── register │ │ ├── test_findParam.py │ │ ├── test_addOrUpCurBact.py │ │ ├── test_initCanSelInfo.py │ │ └── test_getAdultCurbactList.py │ └── perRelated │ │ └── test_addAudltCard.py └── data │ ├── findParam.chlsj │ ├── addOrUpCurBact.chlsj │ ├── addAudltCard.chlsj │ └── getAdultCurbactList.chlsj ├── doc ├── ApiTesting-框架流程图.vsdx └── ApiTesting-项目架构.xmind ├── config ├── apiConfig.yml ├── dbConfig.yml ├── runConfig.yml ├── __init__.py └── test_template.py ├── requirements.txt ├── README.md └── startup.py /comm/script/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /comm/unit/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /logs/2021-02-04_error.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.xml 3 | *.pyc 4 | -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/launch.json: -------------------------------------------------------------------------------- 1 | [ ] -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/environment.json: -------------------------------------------------------------------------------- 1 | [ ] -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/executors.json: -------------------------------------------------------------------------------- 1 | [ ] -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/a10e5441521817af.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/a142325f6ec7dd97.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/a404884c53f9a95e.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/b5dbaecb2dacdb90.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/d57f284c2a250050.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/e5cdc98bcb63fce1.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/e645f31e66475871.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/f658b4378482d4a.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/de7b006637c1f824.attach: -------------------------------------------------------------------------------- 1 | findParam -------------------------------------------------------------------------------- /comm/__init__.py: -------------------------------------------------------------------------------- 1 | # import phoenixdb 2 | # import phoenixdb.cursor -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/64929705a353786a.attach: -------------------------------------------------------------------------------- 1 | addOrUpCurBact -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/d4cfa82e3954b068.attach: -------------------------------------------------------------------------------- 1 | initCanSelInfo -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/3f3d3b675f8b38f0.attach: -------------------------------------------------------------------------------- 1 | getAdultCurbactList -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/aa3749b1bd00dd8e.attach: -------------------------------------------------------------------------------- 1 | getAdultCurbactList -------------------------------------------------------------------------------- /PyDemo/report/xml/13581612-dbff-44e2-b614-28aeaf763e53-attachment.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/xml/15a5ed09-71be-4302-8da3-f1a3833890c3-attachment.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/xml/2d3cbb34-52fb-4b35-80e8-179d043a1226-attachment.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/xml/30403406-d497-4fa4-8a90-e52a5f1723aa-attachment.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/xml/33849d22-c42b-4fd4-b486-acfe3922e91a-attachment.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/xml/a925524d-3c79-42dc-a506-ac9353b81a89-attachment.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/xml/c5f832b3-c5da-4106-8a5d-8bc617600550-attachment.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/xml/eb8ba490-0f39-42ba-9a1c-44e5ee2a0636-attachment.attach: -------------------------------------------------------------------------------- 1 | 200 -------------------------------------------------------------------------------- /PyDemo/report/xml/9487b1b8-64e5-49d0-a0ea-f2254a0a983f-attachment.attach: -------------------------------------------------------------------------------- 1 | findParam -------------------------------------------------------------------------------- /PyDemo/report/html/favicon.ico: -------------------------------------------------------------------------------- 1 | module.exports = __webpack_public_path__ + "favicon.ico"; -------------------------------------------------------------------------------- /PyDemo/report/xml/8a751566-67d8-4a28-943a-a0c8cecc3a9f-attachment.attach: -------------------------------------------------------------------------------- 1 | addOrUpCurBact -------------------------------------------------------------------------------- /PyDemo/report/xml/b6a76b88-e182-454b-ba36-1e34a5c19222-attachment.attach: -------------------------------------------------------------------------------- 1 | initCanSelInfo -------------------------------------------------------------------------------- /PyDemo/report/xml/da39ce35-693c-4f48-92cd-7795dd783e88-attachment.attach: -------------------------------------------------------------------------------- 1 | getAdultCurbactList -------------------------------------------------------------------------------- /PyDemo/report/xml/f1dc7f0e-4445-425a-b4b7-f4b073d49233-attachment.attach: -------------------------------------------------------------------------------- 1 | getAdultCurbactList -------------------------------------------------------------------------------- /logs/2021-02-04.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leozhanggg/ApiTesting/HEAD/logs/2021-02-04.log -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/6d6990d6bc7da779.attach: -------------------------------------------------------------------------------- 1 | http://10.88.88.141:20037/api/register/findParam -------------------------------------------------------------------------------- /PyDemo/report/html/history/duration-trend.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "data" : { 3 | "duration" : 5271 4 | } 5 | } ] -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/duration-trend.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "data" : { 3 | "duration" : 5271 4 | } 5 | } ] -------------------------------------------------------------------------------- /doc/ApiTesting-框架流程图.vsdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leozhanggg/ApiTesting/HEAD/doc/ApiTesting-框架流程图.vsdx -------------------------------------------------------------------------------- /doc/ApiTesting-项目架构.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leozhanggg/ApiTesting/HEAD/doc/ApiTesting-项目架构.xmind -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/47e7333bf43a045.attach: -------------------------------------------------------------------------------- 1 | http://10.88.88.141:20037/api/register/addOrUpCurBact -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/ea0ced6a1ef79518.attach: -------------------------------------------------------------------------------- 1 | http://10.88.88.141:20037/api/register/initCanSelInfo -------------------------------------------------------------------------------- /PyDemo/report/html/history/categories-trend.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "data" : { 3 | "Test defects" : 1 4 | } 5 | } ] -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/categories-trend.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "data" : { 3 | "Test defects" : 1 4 | } 5 | } ] -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/436a2d6b50675cb6.attach: -------------------------------------------------------------------------------- 1 | http://10.88.88.141:20037/api/register/getAdultCurbactList -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/4ac290f03a0b29ab.attach: -------------------------------------------------------------------------------- 1 | http://10.88.88.141:20037/api/register/getAdultCurbactList -------------------------------------------------------------------------------- /PyDemo/report/html/history/retry-trend.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "data" : { 3 | "run" : 4, 4 | "retry" : 0 5 | } 6 | } ] -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/retry-trend.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "data" : { 3 | "run" : 4, 4 | "retry" : 0 5 | } 6 | } ] -------------------------------------------------------------------------------- /PyDemo/report/xml/d354f47a-3693-4b7b-86df-cd34ace4ac9c-attachment.attach: -------------------------------------------------------------------------------- 1 | http://10.88.88.141:20037/api/register/findParam -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/10ea6ae95941448c.attach: -------------------------------------------------------------------------------- 1 | {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/45bb27deeb34ae52.attach: -------------------------------------------------------------------------------- 1 | {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/48d8349a567cd920.attach: -------------------------------------------------------------------------------- 1 | {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/7f88a98d6e750e3c.attach: -------------------------------------------------------------------------------- 1 | {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/d8d657fe62f789ca.attach: -------------------------------------------------------------------------------- 1 | {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} -------------------------------------------------------------------------------- /PyDemo/report/xml/194b21ff-bc74-4712-9e00-2d4d10c529f3-attachment.attach: -------------------------------------------------------------------------------- 1 | http://10.88.88.141:20037/api/register/initCanSelInfo -------------------------------------------------------------------------------- /PyDemo/report/xml/a6f8bf5f-a42a-4c47-a026-243375a5685d-attachment.attach: -------------------------------------------------------------------------------- 1 | http://10.88.88.141:20037/api/register/addOrUpCurBact -------------------------------------------------------------------------------- /PyDemo/report/xml/848e4b5e-7e91-4f72-874b-659053c3e48d-attachment.attach: -------------------------------------------------------------------------------- 1 | http://10.88.88.141:20037/api/register/getAdultCurbactList -------------------------------------------------------------------------------- /PyDemo/report/xml/e9a38fd0-5f1b-4739-a472-7606737e0911-attachment.attach: -------------------------------------------------------------------------------- 1 | http://10.88.88.141:20037/api/register/getAdultCurbactList -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/9c97dfe6f36b3570.attach: -------------------------------------------------------------------------------- 1 | {'success': True, 'code': None, 'msg': '返回成功', 'data': None, 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/5627e81e1f308560.attach: -------------------------------------------------------------------------------- 1 | {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/a2493f73f5b55797.attach: -------------------------------------------------------------------------------- 1 | {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/html/data/categories.csv: -------------------------------------------------------------------------------- 1 | "Category","FAILED","BROKEN","PASSED","SKIPPED","UNKNOWN" 2 | "Test defects","0","1","0","0","0" 3 | -------------------------------------------------------------------------------- /PyDemo/report/xml/067d3035-4727-4009-af05-75776743f64e-attachment.attach: -------------------------------------------------------------------------------- 1 | {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} -------------------------------------------------------------------------------- /PyDemo/report/xml/4f67b9c3-4ae0-4945-9697-c30b6dbbcbf0-attachment.attach: -------------------------------------------------------------------------------- 1 | {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} -------------------------------------------------------------------------------- /PyDemo/report/xml/7c22884c-0191-4937-b2d2-12214a869f4c-attachment.attach: -------------------------------------------------------------------------------- 1 | {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} -------------------------------------------------------------------------------- /PyDemo/report/xml/d3f438ee-fde7-483c-9a1b-87ce48d23359-attachment.attach: -------------------------------------------------------------------------------- 1 | {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} -------------------------------------------------------------------------------- /PyDemo/report/xml/f8618d25-7423-4d9f-a777-b1bc37ee3fd5-attachment.attach: -------------------------------------------------------------------------------- 1 | {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/7a7457e66b250a1f.attach: -------------------------------------------------------------------------------- 1 | {'success': None, 'code': 1, 'msg': '已有该批次的疫苗,请直接修改库存!', 'data': None, 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/xml/5f34e443-5ec3-41cf-9002-dd92ec056d54-attachment.attach: -------------------------------------------------------------------------------- 1 | {'success': True, 'code': None, 'msg': '返回成功', 'data': None, 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/xml/6bc3acef-572c-47fe-9093-56a69faa51ed-attachment.attach: -------------------------------------------------------------------------------- 1 | {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/xml/bc8c8933-6042-4cfe-a825-a19018c34101-attachment.attach: -------------------------------------------------------------------------------- 1 | {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/xml/aa05cb30-25c4-4485-b7f9-1aa4fd98e692-attachment.attach: -------------------------------------------------------------------------------- 1 | {'success': None, 'code': 1, 'msg': '已有该批次的疫苗,请直接修改库存!', 'data': None, 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/640913aa912828ba.attach: -------------------------------------------------------------------------------- 1 | {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/b2611d9bc9f7e7f2.attach: -------------------------------------------------------------------------------- 1 | {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/bdc87a179c292ab3.attach: -------------------------------------------------------------------------------- 1 | {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} -------------------------------------------------------------------------------- /PyDemo/report/html/history/history-trend.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "data" : { 3 | "failed" : 0, 4 | "broken" : 1, 5 | "skipped" : 0, 6 | "passed" : 3, 7 | "unknown" : 0, 8 | "total" : 4 9 | } 10 | } ] -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/history-trend.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "data" : { 3 | "failed" : 0, 4 | "broken" : 1, 5 | "skipped" : 0, 6 | "passed" : 3, 7 | "unknown" : 0, 8 | "total" : 4 9 | } 10 | } ] -------------------------------------------------------------------------------- /PyDemo/report/xml/0d998249-b346-4cb4-a883-985eb7fbd7a1-attachment.attach: -------------------------------------------------------------------------------- 1 | {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} -------------------------------------------------------------------------------- /PyDemo/report/xml/31d021db-66cf-4b6c-ae71-15a2e9953294-attachment.attach: -------------------------------------------------------------------------------- 1 | {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} -------------------------------------------------------------------------------- /PyDemo/report/xml/b3aaf70f-749f-450d-841f-18feaa49b10d-attachment.attach: -------------------------------------------------------------------------------- 1 | {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} -------------------------------------------------------------------------------- /PyDemo/report/html/export/mail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Allure Report summary mail 6 | 7 | 8 | Mail body 9 | 10 | 11 | -------------------------------------------------------------------------------- /PyDemo/report/xml/0e77bd92-752b-4668-8685-730d4b4ba05e-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "654cc911-8aa6-4a5c-a5a8-5b67c3f41bed", "befores": [{"name": "case_data", "status": "passed", "start": 1612427966997, "stop": 1612427966997}], "start": 1612427966997, "stop": 1612427969137} -------------------------------------------------------------------------------- /PyDemo/report/xml/43aa29f7-e92a-473a-9685-6493d9d40c73-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "c9b9f79d-7b60-4b2a-bcf9-990cdc707bf0", "befores": [{"name": "case_data", "status": "passed", "start": 1612427969140, "stop": 1612427969140}], "start": 1612427969140, "stop": 1612427970154} -------------------------------------------------------------------------------- /PyDemo/report/xml/5e3fe95f-3c33-4fda-a519-023a25d338d0-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "37197fb2-8342-4ac8-b8d3-ecf0dcacaaaf", "befores": [{"name": "case_data", "status": "passed", "start": 1612427970157, "stop": 1612427970157}], "start": 1612427970157, "stop": 1612427971195} -------------------------------------------------------------------------------- /PyDemo/report/xml/73339d77-d5f7-4597-8f86-0c8d4816a64e-container.json: -------------------------------------------------------------------------------- 1 | {"uuid": "5a2cc9d7-8d30-4ac6-89f6-fe997b262d17", "befores": [{"name": "case_data", "status": "passed", "start": 1612427971197, "stop": 1612427971197}], "start": 1612427971197, "stop": 1612427972269} -------------------------------------------------------------------------------- /config/apiConfig.yml: -------------------------------------------------------------------------------- 1 | PyDemo: 2 | # 首次会根据接口数据包生成,可自行更改或添加新配置,所有配置将用于公共关联值。 3 | timeout: 10 4 | scheme: http 5 | host: 127.0.0.1:20037 6 | headers: 7 | Content-Type: application/x-www-form-urlencoded;charset=UTF-8 8 | headtoken: xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg= 9 | -------------------------------------------------------------------------------- /PyDemo/report/html/data/behaviors.csv: -------------------------------------------------------------------------------- 1 | "Epic","Feature","Story","FAILED","BROKEN","PASSED","SKIPPED","UNKNOWN" 2 | "","register","test_addOrUpCurBact","0","1","0","0","0" 3 | "","register","test_getAdultCurbactList","0","0","1","0","0" 4 | "","register","test_findParam","0","0","1","0","0" 5 | "","register","test_initCanSelInfo","0","0","1","0","0" 6 | -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/behaviors.json: -------------------------------------------------------------------------------- 1 | { 2 | "total" : 1, 3 | "items" : [ { 4 | "uid" : "f9614baa9d268c2fa96855398ce8a7bf", 5 | "name" : "register", 6 | "statistic" : { 7 | "failed" : 0, 8 | "broken" : 1, 9 | "skipped" : 0, 10 | "passed" : 3, 11 | "unknown" : 0, 12 | "total" : 4 13 | } 14 | } ] 15 | } -------------------------------------------------------------------------------- /comm/utils/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | from comm.utils.readYaml import read_yaml_data 3 | 4 | 5 | def get_case(file_path): 6 | case_yaml = file_path.replace('\\', '/').replace('/testcase/', '/page/').replace('.py', '.yaml') 7 | case_path = os.path.dirname(case_yaml) 8 | case_data = read_yaml_data(case_yaml) 9 | return case_path, case_data 10 | -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/categories.json: -------------------------------------------------------------------------------- 1 | { 2 | "total" : 1, 3 | "items" : [ { 4 | "uid" : "bdbf199525818fae7a8651db9eafe741", 5 | "name" : "Test defects", 6 | "statistic" : { 7 | "failed" : 0, 8 | "broken" : 1, 9 | "skipped" : 0, 10 | "passed" : 0, 11 | "unknown" : 0, 12 | "total" : 1 13 | } 14 | } ] 15 | } -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/suites.json: -------------------------------------------------------------------------------- 1 | { 2 | "total" : 1, 3 | "items" : [ { 4 | "uid" : "2ee94b824b159deda8131714c488ddf3", 5 | "name" : "PyDemo.testcase.register", 6 | "statistic" : { 7 | "failed" : 0, 8 | "broken" : 1, 9 | "skipped" : 0, 10 | "passed" : 3, 11 | "unknown" : 0, 12 | "total" : 4 13 | } 14 | } ] 15 | } -------------------------------------------------------------------------------- /PyDemo/report/html/export/prometheusData.txt: -------------------------------------------------------------------------------- 1 | launch_status_failed 0 2 | launch_status_broken 1 3 | launch_status_passed 3 4 | launch_status_skipped 0 5 | launch_status_unknown 0 6 | launch_time_duration 5271 7 | launch_time_min_duration 1013 8 | launch_time_max_duration 2078 9 | launch_time_sum_duration 5200 10 | launch_problems_test_defects 1 11 | launch_retries_retries 0 12 | launch_retries_run 4 13 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pytest==6.0.2 2 | pytest-html==3.0.0 3 | pytest-xdist==2.1.0 4 | pytest-rerunfailures==9.1.1 5 | allure-pytest==2.8.18 6 | requests==2.24.0 7 | requests-toolbelt==0.9.1 8 | simplejson==3.17.2 9 | ruamel.yaml==0.16.12 10 | PyYAML==5.3.1 11 | configparser==5.0.0 12 | python-dateutil==2.8.0 13 | #elasticsearch==7.13.4 14 | #phoenixdb==1.0.1 15 | #pymysql==1.0.2 16 | #pysolr==3.8.1 17 | #redis==3.5.3 18 | -------------------------------------------------------------------------------- /config/dbConfig.yml: -------------------------------------------------------------------------------- 1 | PyDemo: 2 | # 数据库查询超时时长(不得小于1) 3 | timeout: 3 4 | # MySQL配置信息 5 | mysql_info: 6 | address: 127.0.0.1:3160 7 | db: test 8 | user: test 9 | auth: test 10 | # HBase配置信息(需要启动phoenix查询服务) 11 | hbase_info: 12 | address: 127.0.0.1:8765 13 | db: test 14 | # ES配置信息(需要开放http查询服务) 15 | es_info: 16 | address: 127.0.0.1:9200 17 | db: test 18 | # Solr配置信息 19 | solr_info: 20 | address: 127.0.0.1:8883 21 | -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/summary.json: -------------------------------------------------------------------------------- 1 | { 2 | "reportName" : "Allure Report", 3 | "testRuns" : [ ], 4 | "statistic" : { 5 | "failed" : 0, 6 | "broken" : 1, 7 | "skipped" : 0, 8 | "passed" : 3, 9 | "unknown" : 0, 10 | "total" : 4 11 | }, 12 | "time" : { 13 | "start" : 1612427966998, 14 | "stop" : 1612427972269, 15 | "duration" : 5271, 16 | "minDuration" : 1013, 17 | "maxDuration" : 2078, 18 | "sumDuration" : 5200 19 | } 20 | } -------------------------------------------------------------------------------- /comm/db/__init__.py: -------------------------------------------------------------------------------- 1 | from config import read_yaml_data, DB_CONFIG, PROJECT_NAME 2 | DC = read_yaml_data(DB_CONFIG)[PROJECT_NAME] 3 | if 'solr_info' in DC: 4 | from .querySolr import search_solr 5 | if 'hbase_info' in DC: 6 | from .queryHBase import PhoenixServer 7 | if 'es_info' in DC: 8 | from .queryES import elastic_search 9 | if 'mysql_info' in DC: 10 | from .queryMysql import MysqlServer 11 | if 'redis_info' in DC: 12 | from .queryRedis import exec_redis 13 | -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/d7e1801c64f284ab.attach: -------------------------------------------------------------------------------- 1 | {'params': {'pageType': '', 'unitCode': '3202112002', 'bactCode': '', 'materType': '', 'coreName': '', 'corpSimpName': '', 'materName': '', 'inocCorpCode': '', 'speCodeName': '', 'vaccSpeCode': '', 'pym': '', 'price': '', 'batnmb': '', 'qty': '', 'ifUse': 1, 'dataType': 2, 'createDate': '', 'createManCode': '', 'modifyDate': '', 'modifyManCode': '', 'bactValidate': None, 'bizType': None}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} -------------------------------------------------------------------------------- /PyDemo/report/xml/ae13f7d4-0fd7-42fd-b524-ac0e2af5718a-attachment.attach: -------------------------------------------------------------------------------- 1 | {'params': {'pageType': '', 'unitCode': '3202112002', 'bactCode': '', 'materType': '', 'coreName': '', 'corpSimpName': '', 'materName': '', 'inocCorpCode': '', 'speCodeName': '', 'vaccSpeCode': '', 'pym': '', 'price': '', 'batnmb': '', 'qty': '', 'ifUse': 1, 'dataType': 2, 'createDate': '', 'createManCode': '', 'modifyDate': '', 'modifyManCode': '', 'bactValidate': None, 'bizType': None}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} -------------------------------------------------------------------------------- /PyDemo/report/html/plugins/screen-diff/styles.css: -------------------------------------------------------------------------------- 1 | .screen-diff__switchers { 2 | margin-bottom: 1em; 3 | } 4 | 5 | .screen-diff__switchers label + label { 6 | margin-left: 1em; 7 | } 8 | 9 | .screen-diff__overlay { 10 | position: relative; 11 | cursor: col-resize; 12 | } 13 | 14 | .screen-diff__container { 15 | overflow-x: auto; 16 | } 17 | 18 | .screen-diff__image-over { 19 | top: 0; 20 | left: 0; 21 | bottom: 0; 22 | background: #fff; 23 | position: absolute; 24 | overflow: hidden; 25 | box-shadow: 2px 0 1px -1px #aaa; 26 | } 27 | -------------------------------------------------------------------------------- /PyDemo/page/register/test_initCanSelInfo.yaml: -------------------------------------------------------------------------------- 1 | test_info: 2 | title: register 3 | host: ${host} 4 | scheme: ${scheme} 5 | method: POST 6 | address: /api/register/initCanSelInfo 7 | mime_type: application/x-www-form-urlencoded 8 | headers: ${headers} 9 | timeout: ${timeout} 10 | file: false 11 | cookies: false 12 | premise: false 13 | test_case: 14 | - summary: initCanSelInfo 15 | describe: test_initCanSelInfo 16 | parameter: initCanSelInfo_request.json 17 | check_body: 18 | check_type: check_json 19 | expected_code: 200 20 | expected_result: initCanSelInfo_response.json 21 | -------------------------------------------------------------------------------- /PyDemo/report/html/export/influxDbData.txt: -------------------------------------------------------------------------------- 1 | launch_status failed=0 1612427973000000000 2 | launch_status broken=1 1612427973000000000 3 | launch_status passed=3 1612427973000000000 4 | launch_status skipped=0 1612427973000000000 5 | launch_status unknown=0 1612427973000000000 6 | launch_time duration=5271 1612427973000000000 7 | launch_time min_duration=1013 1612427973000000000 8 | launch_time max_duration=2078 1612427973000000000 9 | launch_time sum_duration=5200 1612427973000000000 10 | launch_problems test_defects=1 1612427973000000000 11 | launch_retries retries=0 1612427973000000000 12 | launch_retries run=4 1612427973000000000 13 | -------------------------------------------------------------------------------- /comm/utils/readJson.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2020/12/03 3 | # @Author : Leo Zhang 4 | # @File : readJson.py 5 | # *********************** 6 | import json 7 | 8 | 9 | def read_json_data(json_file): 10 | """读取json文件数据 11 | 12 | :param json_file: json文件地址 13 | :return: 14 | """ 15 | with open(json_file, "r", encoding="utf-8") as fr: 16 | return json.load(fr) 17 | 18 | 19 | def write_json_file(json_file, obj): 20 | """把对象obj写入json文件 21 | 22 | :param json_file: json文件地址 23 | :param obj: 数据对象 24 | :return: 25 | """ 26 | with open(json_file, "w", encoding='utf-8') as fw: 27 | json.dump(obj, fw, ensure_ascii=False, indent=4) 28 | -------------------------------------------------------------------------------- /PyDemo/page/register/test_addOrUpCurBact.yaml: -------------------------------------------------------------------------------- 1 | test_info: 2 | title: register 3 | host: ${host} 4 | scheme: ${scheme} 5 | method: POST 6 | address: /api/register/addOrUpCurBact 7 | mime_type: application/x-www-form-urlencoded 8 | headers: ${headers} 9 | timeout: ${timeout} 10 | file: false 11 | cookies: false 12 | premise: /register/test_getAdultCurbactList.yaml 13 | test_case: 14 | - summary: addOrUpCurBact 15 | describe: test_addOrUpCurBact 16 | parameter: addOrUpCurBact_request.json 17 | check_body: 18 | check_type: check_json 19 | expected_code: 200 20 | expected_result: 21 | success: true 22 | code: 23 | msg: 返回成功 24 | data: 25 | callTime: 26 | -------------------------------------------------------------------------------- /comm/utils/readYaml.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2020/12/03 3 | # @Author : Leo Zhang 4 | # @File : readYaml.py 5 | # *********************** 6 | 7 | 8 | def read_yaml_data(yaml_file): 9 | """读取yaml文件数据 10 | 11 | :param yaml_file: yaml文件地址 12 | :return: 13 | """ 14 | import yaml 15 | with open(yaml_file, 'r', encoding="utf-8") as fr: 16 | return yaml.load(fr, Loader=yaml.SafeLoader) 17 | 18 | 19 | def write_yaml_file(yaml_file, obj): 20 | """把对象obj写入yaml文件 21 | 22 | :param yaml_file: yaml文件地址 23 | :param obj: 数据对象 24 | :return: 25 | """ 26 | from ruamel import yaml 27 | with open(yaml_file, 'w', encoding='utf-8') as fw: 28 | yaml.dump(obj, fw, Dumper=yaml.RoundTripDumper, allow_unicode=True) 29 | -------------------------------------------------------------------------------- /PyDemo/page/register/test_getAdultCurbactList.yaml: -------------------------------------------------------------------------------- 1 | test_info: 2 | title: register 3 | host: ${host} 4 | scheme: ${scheme} 5 | method: POST 6 | address: /api/register/getAdultCurbactList 7 | mime_type: application/x-www-form-urlencoded 8 | headers: ${headers} 9 | timeout: ${timeout} 10 | file: false 11 | cookies: false 12 | premise: false 13 | test_case: 14 | - summary: getAdultCurbactList 15 | describe: test_getAdultCurbactList 16 | parameter: 17 | params: 18 | unitCode: '3202112002' 19 | first: 0 20 | pym: '' 21 | pageSize: 10 22 | page: 0 23 | headtoken: ${headtoken} 24 | check_body: 25 | check_type: check_json 26 | expected_code: 200 27 | expected_result: getAdultCurbactList_response.json 28 | -------------------------------------------------------------------------------- /PyDemo/report/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Allure Report 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /config/runConfig.yml: -------------------------------------------------------------------------------- 1 | # 运行项目名 2 | project_name: PyDemo 3 | 4 | # 运行模式: 5 | auto_switch: 2 6 | # 0 -不开启自动生成测试用例功能,将直接运行测试 7 | # 1 -根据手工编写用例,自动生成测试脚本,然后运行测试 8 | # 2 -根据接口抓包数据,自动生成测试用例和测试脚本,然后运行测试 9 | # 3 -根据接口抓包数据,自动生成测试用例和测试脚本,但不运行测试 10 | # 注意:目前解析仅支持(.chlsj)格式,请使用Charles工具抓包导出JSON Session File 11 | 12 | # 扫描测试用例目录(且仅当auto_switch=1时有用) 13 | scan_dir: 14 | 15 | # 使用模糊匹配测试用例(空则匹配所有) 16 | pattern: 17 | 18 | # 执行并发线程数(0表示不开启) 19 | process: 0 20 | 21 | # 失败重试次数(0表示不重试) 22 | reruns: 0 23 | 24 | # 本轮测试最大允许失败数(超出则立即结束测试) 25 | maxfail: 20 26 | 27 | # 接口调用间隔时间(s) 28 | interval: 1 29 | 30 | # 测试结果校验方式说明(共5种方式): 31 | # no_check:不做任何校验 32 | # check_code:仅校验接口返回码code 33 | # check_json:校验接口返回码code,并进行json格式比较返回结果(默认方式) 34 | # entirely_check:校验接口返回码code,并进行完整比较返回结果 35 | # regular_check:校验接口返回码code,并进行正则匹配返回结果 -------------------------------------------------------------------------------- /PyDemo/page/register/test_findParam.yaml: -------------------------------------------------------------------------------- 1 | test_info: 2 | title: register 3 | host: ${host} 4 | scheme: ${scheme} 5 | method: POST 6 | address: /api/register/findParam 7 | mime_type: application/x-www-form-urlencoded 8 | headers: ${headers} 9 | timeout: ${timeout} 10 | file: false 11 | cookies: false 12 | premise: false 13 | test_case: 14 | - summary: findParam 15 | describe: test_findParam 16 | parameter: 17 | params: 18 | unitCode: '3202112002' 19 | first: 0 20 | pym: '' 21 | pageSize: 10 22 | page: 0 23 | headtoken: ${headtoken} 24 | check_body: 25 | check_type: check_json 26 | expected_code: 200 27 | expected_result: 28 | success: true 29 | code: 30 | msg: 返回成功 31 | data: 32 | - '1' 33 | - '1' 34 | callTime: 35 | -------------------------------------------------------------------------------- /PyDemo/report/html/data/suites.csv: -------------------------------------------------------------------------------- 1 | "Status","Start Time","Stop Time","Duration in ms","Parent Suite","Suite","Sub Suite","Test Class","Test Method","Name","Description" 2 | "broken","Thu Feb 04 16:39:26 CST 2021","Thu Feb 04 16:39:29 CST 2021","2078","PyDemo.testcase.register","test_addOrUpCurBact","TestRegister","","","test_addOrUpCurBact[case_data0]","" 3 | "passed","Thu Feb 04 16:39:30 CST 2021","Thu Feb 04 16:39:31 CST 2021","1038","PyDemo.testcase.register","test_getAdultCurbactList","TestRegister","","","test_getAdultCurbactList[case_data0]","" 4 | "passed","Thu Feb 04 16:39:29 CST 2021","Thu Feb 04 16:39:30 CST 2021","1013","PyDemo.testcase.register","test_findParam","TestRegister","","","test_findParam[case_data0]","" 5 | "passed","Thu Feb 04 16:39:31 CST 2021","Thu Feb 04 16:39:32 CST 2021","1071","PyDemo.testcase.register","test_initCanSelInfo","TestRegister","","","test_initCanSelInfo[case_data0]","" 6 | -------------------------------------------------------------------------------- /config/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2020/12/03 3 | # @Author : Leo Zhang 4 | # @File : __init__.py 5 | # *********************** 6 | from comm.utils.readYaml import read_yaml_data 7 | import os 8 | 9 | # 获取主目录路径 10 | ROOT_DIR = str(os.path.realpath(__file__)).split('config')[0].replace('\\', '/') 11 | 12 | # 获取配置文件路径 13 | API_CONFIG = ROOT_DIR+'config/apiConfig.yml' 14 | RUN_CONFIG = ROOT_DIR+'config/runConfig.yml' 15 | DB_CONFIG = ROOT_DIR+'config/dbConfig.yml' 16 | 17 | # 获取运行配置信息 18 | RC = read_yaml_data(RUN_CONFIG) 19 | INTERVAL = RC['interval'] 20 | PROJECT_NAME = RC['project_name'] 21 | 22 | # 接口数据目录(.chlsj文件) 23 | DATA_DIR = ROOT_DIR+PROJECT_NAME+'/data' 24 | # 测试数据目录(test.yaml) 25 | PAGE_DIR = ROOT_DIR+PROJECT_NAME+'/page' 26 | # 测试脚本目录(test.py) 27 | TEST_DIR = ROOT_DIR+PROJECT_NAME+'/testcase' 28 | # 测试报告目录(xml|html) 29 | REPORT_DIR = ROOT_DIR+PROJECT_NAME+'/report' 30 | 31 | -------------------------------------------------------------------------------- /config/test_template.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/2/2 3 | # @Author : Leo Zhang 4 | # @File : test_template.py 5 | # **************************** 6 | import os 7 | import allure 8 | import pytest 9 | from comm.utils import get_case 10 | from comm.unit.initializePremise import init_premise 11 | from comm.unit.apiSend import send_request 12 | from comm.unit.checkResult import check_result 13 | case_path, case_data = get_case(os.path.realpath(__file__)) 14 | 15 | 16 | @allure.feature(case_data["test_info"]["title"]) 17 | class TestTemplate: 18 | 19 | @pytest.mark.parametrize("test_case", case_data["test_case"]) 20 | @allure.story("test_template") 21 | def test_template(self, test_case): 22 | # 初始化请求:执行前置接口+替换关联变量 23 | test_info, test_case = init_premise(case_data["test_info"], test_case, case_path) 24 | # 发送当前接口 25 | code, data = send_request(test_info, test_case) 26 | # 校验接口返回 27 | check_result(test_case, code, data) 28 | -------------------------------------------------------------------------------- /PyDemo/page/register/initCanSelInfo_request.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "summary": "initCanSelInfo", 4 | "body": { 5 | "params": { 6 | "pageType": "", 7 | "unitCode": "3202112002", 8 | "bactCode": "", 9 | "materType": "", 10 | "coreName": "", 11 | "corpSimpName": "", 12 | "materName": "", 13 | "inocCorpCode": "", 14 | "speCodeName": "", 15 | "vaccSpeCode": "", 16 | "pym": "", 17 | "price": "", 18 | "batnmb": "", 19 | "qty": "", 20 | "ifUse": 1, 21 | "dataType": 2, 22 | "createDate": "", 23 | "createManCode": "", 24 | "modifyDate": "", 25 | "modifyManCode": "", 26 | "bactValidate": null, 27 | "bizType": null 28 | }, 29 | "headtoken": "${headtoken}" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/duration.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "uid" : "e5c5230705b9bfbb", 3 | "name" : "test_addOrUpCurBact[case_data0]", 4 | "time" : { 5 | "start" : 1612427966998, 6 | "stop" : 1612427969076, 7 | "duration" : 2078 8 | }, 9 | "status" : "broken", 10 | "severity" : "normal" 11 | }, { 12 | "uid" : "7d4ed4f7a18b20d4", 13 | "name" : "test_getAdultCurbactList[case_data0]", 14 | "time" : { 15 | "start" : 1612427970157, 16 | "stop" : 1612427971195, 17 | "duration" : 1038 18 | }, 19 | "status" : "passed", 20 | "severity" : "normal" 21 | }, { 22 | "uid" : "10d4bd6301177f6", 23 | "name" : "test_findParam[case_data0]", 24 | "time" : { 25 | "start" : 1612427969141, 26 | "stop" : 1612427970154, 27 | "duration" : 1013 28 | }, 29 | "status" : "passed", 30 | "severity" : "normal" 31 | }, { 32 | "uid" : "aa8dfcaa510813c2", 33 | "name" : "test_initCanSelInfo[case_data0]", 34 | "time" : { 35 | "start" : 1612427971198, 36 | "stop" : 1612427972269, 37 | "duration" : 1071 38 | }, 39 | "status" : "passed", 40 | "severity" : "normal" 41 | } ] -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/severity.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "uid" : "e5c5230705b9bfbb", 3 | "name" : "test_addOrUpCurBact[case_data0]", 4 | "time" : { 5 | "start" : 1612427966998, 6 | "stop" : 1612427969076, 7 | "duration" : 2078 8 | }, 9 | "status" : "broken", 10 | "severity" : "normal" 11 | }, { 12 | "uid" : "10d4bd6301177f6", 13 | "name" : "test_findParam[case_data0]", 14 | "time" : { 15 | "start" : 1612427969141, 16 | "stop" : 1612427970154, 17 | "duration" : 1013 18 | }, 19 | "status" : "passed", 20 | "severity" : "normal" 21 | }, { 22 | "uid" : "aa8dfcaa510813c2", 23 | "name" : "test_initCanSelInfo[case_data0]", 24 | "time" : { 25 | "start" : 1612427971198, 26 | "stop" : 1612427972269, 27 | "duration" : 1071 28 | }, 29 | "status" : "passed", 30 | "severity" : "normal" 31 | }, { 32 | "uid" : "7d4ed4f7a18b20d4", 33 | "name" : "test_getAdultCurbactList[case_data0]", 34 | "time" : { 35 | "start" : 1612427970157, 36 | "stop" : 1612427971195, 37 | "duration" : 1038 38 | }, 39 | "status" : "passed", 40 | "severity" : "normal" 41 | } ] -------------------------------------------------------------------------------- /PyDemo/report/html/widgets/status-chart.json: -------------------------------------------------------------------------------- 1 | [ { 2 | "uid" : "e5c5230705b9bfbb", 3 | "name" : "test_addOrUpCurBact[case_data0]", 4 | "time" : { 5 | "start" : 1612427966998, 6 | "stop" : 1612427969076, 7 | "duration" : 2078 8 | }, 9 | "status" : "broken", 10 | "severity" : "normal" 11 | }, { 12 | "uid" : "7d4ed4f7a18b20d4", 13 | "name" : "test_getAdultCurbactList[case_data0]", 14 | "time" : { 15 | "start" : 1612427970157, 16 | "stop" : 1612427971195, 17 | "duration" : 1038 18 | }, 19 | "status" : "passed", 20 | "severity" : "normal" 21 | }, { 22 | "uid" : "10d4bd6301177f6", 23 | "name" : "test_findParam[case_data0]", 24 | "time" : { 25 | "start" : 1612427969141, 26 | "stop" : 1612427970154, 27 | "duration" : 1013 28 | }, 29 | "status" : "passed", 30 | "severity" : "normal" 31 | }, { 32 | "uid" : "aa8dfcaa510813c2", 33 | "name" : "test_initCanSelInfo[case_data0]", 34 | "time" : { 35 | "start" : 1612427971198, 36 | "stop" : 1612427972269, 37 | "duration" : 1071 38 | }, 39 | "status" : "passed", 40 | "severity" : "normal" 41 | } ] -------------------------------------------------------------------------------- /PyDemo/report/html/data/categories.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid" : "4b4757e66a1912dae1a509f688f20b0f", 3 | "name" : "categories", 4 | "children" : [ { 5 | "name" : "Test defects", 6 | "children" : [ { 7 | "name" : "Exception: JSON格式校验,关键字 success 返回结果 True 与期望结果 None 类型不符", 8 | "children" : [ { 9 | "name" : "test_addOrUpCurBact[case_data0]", 10 | "uid" : "e5c5230705b9bfbb", 11 | "parentUid" : "c54c7aeb99bc40822dbbe6fd6c068928", 12 | "status" : "broken", 13 | "time" : { 14 | "start" : 1612427966998, 15 | "stop" : 1612427969076, 16 | "duration" : 2078 17 | }, 18 | "flaky" : false, 19 | "newFailed" : false, 20 | "parameters" : [ "{'summary': 'addOrUpCurBact', 'describe': 'test_addOrUpCurBact', 'parameter': 'addOrUpCurBact_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': None, 'callTime': None}}}" ] 21 | } ], 22 | "uid" : "c54c7aeb99bc40822dbbe6fd6c068928" 23 | } ], 24 | "uid" : "bdbf199525818fae7a8651db9eafe741" 25 | } ] 26 | } -------------------------------------------------------------------------------- /PyDemo/testcase/register/test_findParam.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/2/2 3 | # @Author : Leo Zhang 4 | # @File : test_findParam.py 5 | # **************************** 6 | import os 7 | import allure 8 | import pytest 9 | from comm.utils.readYaml import read_yaml_data 10 | from comm.unit.initializePremise import init_premise 11 | from comm.unit.apiSend import send_request 12 | from comm.unit.checkResult import check_result 13 | file_path = os.path.realpath(__file__).replace('\\', '/') 14 | case_yaml = file_path.replace('/testcase/', '/page/').replace('.py', '.yaml') 15 | test_case = read_yaml_data(case_yaml) 16 | 17 | 18 | @allure.feature(test_case["test_info"]["title"]) 19 | class TestRegister: 20 | 21 | @pytest.mark.parametrize("test_case", test_case["test_case"]) 22 | @allure.story("test_findParam") 23 | def test_findParam(self, test_case): 24 | # 初始化请求:执行前置接口+替换关联变量 25 | test_info, test_case = init_premise(test_case["test_info"], test_case, case_yaml) 26 | # 发送当前接口 27 | code, data = send_request(test_info, test_case) 28 | # 校验接口返回 29 | check_result(test_case, code, data) 30 | -------------------------------------------------------------------------------- /PyDemo/testcase/perRelated/test_addAudltCard.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/2/2 3 | # @Author : Leo Zhang 4 | # @File : test_addAudltCard.py 5 | # **************************** 6 | import os 7 | import allure 8 | import pytest 9 | from comm.utils.readYaml import read_yaml_data 10 | from comm.unit.initializePremise import init_premise 11 | from comm.unit.apiSend import send_request 12 | from comm.unit.checkResult import check_result 13 | file_path = os.path.realpath(__file__).replace('\\', '/') 14 | case_yaml = file_path.replace('/testcase/', '/page/').replace('.py', '.yaml') 15 | test_case = read_yaml_data(case_yaml) 16 | 17 | 18 | @allure.feature(test_case["test_info"]["title"]) 19 | class TestPerrelated: 20 | 21 | @pytest.mark.parametrize("test_case", test_case["test_case"]) 22 | @allure.story("test_addAudltCard") 23 | def test_addAudltCard(self, test_case): 24 | # 初始化请求:执行前置接口+替换关联变量 25 | test_info, test_case = init_premise(test_case["test_info"], test_case, case_yaml) 26 | # 发送当前接口 27 | code, data = send_request(test_info, test_case) 28 | # 校验接口返回 29 | check_result(test_case, code, data) 30 | -------------------------------------------------------------------------------- /PyDemo/testcase/register/test_addOrUpCurBact.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/2/2 3 | # @Author : Leo Zhang 4 | # @File : test_addOrUpCurBact.py 5 | # **************************** 6 | import os 7 | import allure 8 | import pytest 9 | from comm.utils.readYaml import read_yaml_data 10 | from comm.unit.initializePremise import init_premise 11 | from comm.unit.apiSend import send_request 12 | from comm.unit.checkResult import check_result 13 | file_path = os.path.realpath(__file__).replace('\\', '/') 14 | case_yaml = file_path.replace('/testcase/', '/page/').replace('.py', '.yaml') 15 | case_data = read_yaml_data(case_yaml) 16 | 17 | 18 | @allure.feature(case_data["test_info"]["title"]) 19 | class TestRegister: 20 | 21 | @pytest.mark.parametrize("test_case", case_data["test_case"]) 22 | @allure.story("test_addOrUpCurBact") 23 | def test_addOrUpCurBact(self, test_case): 24 | # 初始化请求:执行前置接口+替换关联变量 25 | test_info, test_case = init_premise(case_data["test_info"], test_case, case_yaml) 26 | # 发送当前接口 27 | code, data = send_request(test_info, test_case) 28 | # 校验接口返回 29 | check_result(test_case, code, data) 30 | -------------------------------------------------------------------------------- /PyDemo/testcase/register/test_initCanSelInfo.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/2/2 3 | # @Author : Leo Zhang 4 | # @File : test_initCanSelInfo.py 5 | # **************************** 6 | import os 7 | import allure 8 | import pytest 9 | from comm.utils.readYaml import read_yaml_data 10 | from comm.unit.initializePremise import init_premise 11 | from comm.unit.apiSend import send_request 12 | from comm.unit.checkResult import check_result 13 | file_path = os.path.realpath(__file__).replace('\\', '/') 14 | case_yaml = file_path.replace('/testcase/', '/page/').replace('.py', '.yaml') 15 | test_case = read_yaml_data(case_yaml) 16 | 17 | 18 | @allure.feature(test_case["test_info"]["title"]) 19 | class TestRegister: 20 | 21 | @pytest.mark.parametrize("test_case", test_case["test_case"]) 22 | @allure.story("test_initCanSelInfo") 23 | def test_initCanSelInfo(self, test_case): 24 | # 初始化请求:执行前置接口+替换关联变量 25 | test_info, test_case = init_premise(test_case["test_info"], test_case, case_yaml) 26 | # 发送当前接口 27 | code, data = send_request(test_info, test_case) 28 | # 校验接口返回 29 | check_result(test_case, code, data) 30 | -------------------------------------------------------------------------------- /PyDemo/testcase/register/test_getAdultCurbactList.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/2/2 3 | # @Author : Leo Zhang 4 | # @File : test_getAdultCurbactList.py 5 | # **************************** 6 | import os 7 | import allure 8 | import pytest 9 | from comm.utils.readYaml import read_yaml_data 10 | from comm.unit.initializePremise import init_premise 11 | from comm.unit.apiSend import send_request 12 | from comm.unit.checkResult import check_result 13 | file_path = os.path.realpath(__file__).replace('\\', '/') 14 | case_yaml = file_path.replace('/testcase/', '/page/').replace('.py', '.yaml') 15 | test_case = read_yaml_data(case_yaml) 16 | 17 | 18 | @allure.feature(test_case["test_info"]["title"]) 19 | class TestRegister: 20 | 21 | @pytest.mark.parametrize("test_case", test_case["test_case"]) 22 | @allure.story("test_getAdultCurbactList") 23 | def test_getAdultCurbactList(self, test_case): 24 | # 初始化请求:执行前置接口+替换关联变量 25 | test_info, test_case = init_premise(test_case["test_info"], test_case, case_yaml) 26 | # 发送当前接口 27 | code, data = send_request(test_info, test_case) 28 | # 校验接口返回 29 | check_result(test_case, code, data) 30 | -------------------------------------------------------------------------------- /PyDemo/page/register/addOrUpCurBact_request.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "summary": "addOrUpCurBact", 4 | "body": { 5 | "params": { 6 | "pageType": "0", 7 | "unitCode": "${unitCode}", 8 | "bactCode": "280101", 9 | "materType": "86901119000052", 10 | "coreName": "大连雅立峰", 11 | "corpSimpName": "大连雅立峰", 12 | "materName": "狂犬病疫苗(vero细胞)", 13 | "inocCorpCode": "50", 14 | "speCodeName": "1.0ml", 15 | "vaccSpeCode": "1002", 16 | "pym": "kqbymveroxb", 17 | "price": "0", 18 | "batnmb": "20110101", 19 | "qty": "100", 20 | "ifUse": 1, 21 | "dataType": 2, 22 | "createDate": "", 23 | "createManCode": "${createManCode}", 24 | "modifyDate": "", 25 | "modifyManCode": "${createManCode}", 26 | "bactValidate": "$GenDate(y+1)", 27 | "bizType": 1, 28 | "materTypeCode": "1" 29 | }, 30 | "headtoken": "${headtoken}" 31 | } 32 | } 33 | ] -------------------------------------------------------------------------------- /PyDemo/page/perRelated/addAudltCard_request.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "summary": "addAudltCard", 4 | "body": { 5 | "params": { 6 | "adultAddressregion": "3202000000", 7 | "adultAddressdistrict": "AUTO99", 8 | "adultCountryCode": "156", 9 | "adultNationCode": "1001", 10 | "adultNoType": "2", 11 | "adultHabiCode": "32021100", 12 | "unitCode": "3202112002", 13 | "adultAccountCode": 1002, 14 | "adultResiCode": 1, 15 | "adultNo": "$RandInt(10000000,99999999)", 16 | "adultName": "AUTO99", 17 | "adultSex": "1", 18 | "adultBirthday": "2015-03-03", 19 | "adultMobile": "19999999999", 20 | "adultHabiaddress": "AUTO99", 21 | "adultArtimove": 0, 22 | "adultIfdead": 0, 23 | "adultHereCode": 1001, 24 | "adultCreatesite": "3202112002", 25 | "adultCreatemanName": "马山山", 26 | "adultCreateman": "3202112002008", 27 | "adultCreatesiteName": "马山社区" 28 | }, 29 | "headtoken": "${headtoken}" 30 | } 31 | } 32 | ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ApiTesting 2 | 此框架是基于Python+Pytest+Requests+Allure+Yaml+Json实现全链路接口自动化测试。 3 | 4 | 主要流程: 5 | 6 | > 解析接口数据包 ->生成接口基础配置(yml) ->生成测试用例(yaml+json) ->生成测试脚本(.py) ->运行测试(pytest) ->生成测试报告(allure) 7 | 8 | 测试流程: 9 | 10 | > 初始化请求 ->处理接口基础信息 ->读取前置接口用例 ->发送前置接口 ->处理当前接口数据 ->发送当前接口 ->检查接口返回 11 | 12 | ApiTesting全链路接口自动化测试框架 - 初版(一) 13 | > 介绍:https://www.cnblogs.com/leozhanggg/p/14373878.html 14 | 15 | ApiTesting全链路接口自动化测试框架 - 新增数据库校验(二) 16 | > 介绍:https://www.cnblogs.com/leozhanggg/p/14522084.html 17 | 18 | ApiTesting全链路接口自动化测试框架 - 实战应用 19 | > 介绍:https://www.cnblogs.com/leozhanggg/p/14519800.html 20 | 21 | 运行配置说明: 22 | 23 | > 运行项目名 24 | project_name: PyDemo 25 | 26 | > 运行模式: 27 | auto_switch: 2 28 | 29 | > 0 - 不开启自动生成测试用例功能,将直接运行测试 30 | 31 | > 1 - 根据手工编写用例,自动生成测试脚本,然后运行测试 32 | 33 | > 2 - 根据接口抓包数据,自动生成测试用例和测试脚本,然后运行测试 34 | 35 | > 3 - 根据接口抓包数据,自动生成测试用例和测试脚本,但不运行测试 36 | 37 | > 注意:目前解析仅支持(.chlsj)格式,请使用Charles工具抓包导出JSON Session File 38 | 39 | > 扫描测试用例目录(且仅当auto_switch=1时有用) 40 | scan_dir: 41 | 42 | > 使用模糊匹配测试用例(空则匹配所有) 43 | pattern: 44 | 45 | > 执行并发线程数(0表示不开启) 46 | process: 0 47 | 48 | > 失败重试次数(0表示不重试) 49 | reruns: 0 50 | 51 | > 本轮测试最大允许失败数(超出则立即结束测试) 52 | maxfail: 20 53 | 54 | > 接口调用间隔时间(s) 55 | interval: 1 56 | 57 | > 测试结果校验方式说明(共5种方式): 58 | 59 | > 1 - no_check:不做任何校验 60 | 61 | > 2 - check_code:仅校验接口返回码code 62 | 63 | > 3 - check_json:校验接口返回码code,并进行json格式比较返回结果(默认方式) 64 | 65 | > 4 - entirely_check:校验接口返回码code,并进行完整比较返回结果 66 | 67 | > 5 - regular_check:校验接口返回码code,并进行正则匹配返回结果 68 | 69 | -------------------------------------------------------------------------------- /PyDemo/page/perRelated/test_addAudltCard.yaml: -------------------------------------------------------------------------------- 1 | test_info: 2 | title: perRelated 3 | host: ${host} 4 | scheme: ${scheme} 5 | method: POST 6 | address: /api/perRelated/addAudltCard 7 | mime_type: application/x-www-form-urlencoded 8 | headers: ${headers} 9 | timeout: ${timeout} 10 | file: false 11 | cookies: false 12 | premise: false 13 | test_case: 14 | - summary: addAudltCard 15 | describe: test_addAudltCard 16 | parameter: addAudltCard_request.json 17 | check_body: 18 | check_type: check_json 19 | expected_code: 200 20 | expected_result: addAudltCard_response.json 21 | check_db: 22 | - check_type: mysql 23 | execute_sql: select * from TD_ADULT where ADULT_CODE='${adultCode}' 24 | expected_result: 25 | - ADULT_CODE: ${adultCode} 26 | ADULT_NAME: AUTO99 27 | ADULT_SEX: 1 28 | ADULT_BIRTHDAY: 2015-03-03 29 | ADULT_MOBILE: 19999999999 30 | - check_type: es 31 | execute_sql: select * from adult where CHIL_NAME='AUTO99' 32 | expected_result: 33 | - CHIL_NAME: AUTO99 34 | CHIL_SEX: 1 35 | CHIL_MOBILE: 19999999999 36 | - CHIL_NAME: AUTO99 37 | CHIL_SEX: 1 38 | CHIL_MOBILE: 19999999999 39 | - check_type: solr 40 | execute_sql: select * from adultsolr320000 where adultName='AUTO99' 41 | expected_result: 42 | - adultName: AUTO99 43 | adultSex: 1 44 | adultMobile: 19999999999 45 | - check_type: hbase 46 | execute_sql: select * from TD_ADULT_YZ where ADULT_CODE=3202112002803000001 47 | expected_result: 48 | - ADULT_CODE: 3202112002803000001 -------------------------------------------------------------------------------- /comm/script/writeLogs.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2020/9/22 3 | # @Author : Leo Zhang 4 | # @File : writeLogs.py 5 | # ************************ 6 | import logging 7 | import time 8 | import sys 9 | import os 10 | 11 | 12 | class MyLogs: 13 | 14 | def __init__(self, log_path): 15 | # 定义日志默认路径和日志名称 16 | if not os.path.exists(log_path): 17 | os.makedirs(log_path) 18 | runtime = time.strftime('%Y-%m-%d', time.localtime(time.time())) 19 | logfile = os.path.join(log_path, runtime+'.log') 20 | logfile_err = os.path.join(log_path, runtime+'_error.log') 21 | 22 | # 第一步,初始化日志对象并设置日志等级 23 | logger = logging.getLogger() 24 | logger.setLevel(logging.DEBUG) 25 | logger.handlers = [] 26 | 27 | # 第二步,创建一个handler,用于写入debug日志文件 28 | fh = logging.FileHandler(logfile, mode='a+') 29 | fh.setLevel(logging.DEBUG) 30 | 31 | # 第三步,创建一个handler,用于写入error日志文件 32 | fh_err = logging.FileHandler(logfile_err, mode='a+') 33 | fh_err.setLevel(logging.ERROR) 34 | 35 | # 第四步,再创建一个handler,用于输出info日志到控制台 36 | sh = logging.StreamHandler(sys.stdout) 37 | sh.setLevel(logging.INFO) 38 | 39 | # 第五步,定义handler的输出格式 40 | formatter = logging.Formatter("%(asctime)s - %(filename)s - %(levelname)s: %(message)s") 41 | fh.setFormatter(formatter) 42 | fh_err.setFormatter(formatter) 43 | sh.setFormatter(formatter) 44 | 45 | # 第六步,将logger添加到handler里面 46 | logger.addHandler(fh) 47 | logger.addHandler(fh_err) 48 | logger.addHandler(sh) 49 | -------------------------------------------------------------------------------- /comm/db/queryRedis.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/03/09 3 | # @Author : Leo Zhang 4 | # @File : queryRedis.py 5 | # ************************** 6 | import logging 7 | import redis 8 | 9 | 10 | def exec_redis(address, auth, db_num, db_type, key): 11 | """获取redis数据 12 | 13 | :param address: 内存库地址(格式:ip:port) 14 | :param auth: 内存库密码 15 | :param db_num: 查询内存库号 16 | :param db_type: 数据库类型 17 | :param key: 查询key值 18 | :return: 19 | """ 20 | # 初始化redis连接 21 | host, port = address.split(':') 22 | logging.debug('Redis Info: host={}, port={}, auth={}, db={}, type={}' 23 | .format(host, port, auth, db_num, db_type)) 24 | conn = redis.StrictRedis(host=host, port=int(port), db=db_num, 25 | password=auth, decode_responses=True) 26 | logging.info('执行查询>>> db={}, key={}'.format(db_num, key)) 27 | 28 | # 获取string类型指定key的对应值 29 | if 'string' in db_type: 30 | result = conn.get(key) 31 | # 获取hash类型指定key的所有数据 32 | elif 'hash' in db_type: 33 | result = conn.hgetall(key) 34 | # 获取zset类型指定key的前50行数据 35 | elif 'zset' in db_type: 36 | result = conn.zrange(key, 0, 50, desc=False, 37 | withscores=True, score_cast_func=int) 38 | # 获取set类型指定key的所有数据 39 | elif 'set' in db_type: 40 | result = conn.smembers(key) 41 | # 获取list类型指定key的前10个数据 42 | elif 'list' in db_type: 43 | result = conn.lrange(key, 0, 10) 44 | else: 45 | raise Exception('未知的数据类型{},请检查dbinfo配置'.format(db_type)) 46 | 47 | logging.info('查询结果>>> {}'.format(result)) 48 | return result 49 | -------------------------------------------------------------------------------- /startup.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/2/1 3 | # @Author : Leo Zhang 4 | # @File : startup.py 5 | # *********************** 6 | import os 7 | import sys 8 | import pytest 9 | import logging 10 | 11 | 12 | if __name__ == '__main__': 13 | from comm.script import writeLogs, writeCase 14 | from config import * 15 | 16 | # 开启日志记录(默认logs目录) 17 | writeLogs.MyLogs(ROOT_DIR+'logs') 18 | 19 | # 判断运行模式 20 | if RC['auto_switch'] == 3: 21 | logging.info("根据接口抓包数据,自动生成测试用例和测试脚本,但不运行测试!") 22 | writeCase.write_case(DATA_DIR, auto_yaml=True) 23 | sys.exit(0) 24 | 25 | elif RC['auto_switch'] == 2: 26 | logging.info("根据接口抓包数据,自动生成测试用例和测试脚本,然后运行测试!") 27 | writeCase.write_case(DATA_DIR, auto_yaml=True) 28 | 29 | elif RC['auto_switch'] == 1: 30 | # 如果扫描路径为空在则取项目page目录 31 | if not RC['scan_dir']: 32 | RC['scan_dir'] = PAGE_DIR 33 | logging.info("根据手工编写用例,自动生成测试脚本,然后运行测试!") 34 | writeCase.write_case(RC['scan_dir'], auto_yaml=False) 35 | 36 | else: 37 | logging.info("不开启自动生成测试用例功能,将直接运行测试!") 38 | 39 | # 定义运行参数 40 | args_list = ['-vs', TEST_DIR, 41 | '-n', str(RC['process']), 42 | '--reruns', str(RC['reruns']), 43 | '--maxfail', str(RC['maxfail']), 44 | '--alluredir', REPORT_DIR+'/xml', 45 | '--clean-alluredir', 46 | '--disable-warnings'] 47 | # 判断是否开启用例匹配 48 | if RC['pattern']: 49 | args_list += ['-k ' + str(RC['pattern'])] 50 | test_result = pytest.main(args_list) 51 | 52 | # 生成allure报告 53 | cmd = 'allure generate --clean %s -o %s ' % (REPORT_DIR+'/xml', REPORT_DIR+'/html') 54 | os.system(cmd) 55 | -------------------------------------------------------------------------------- /comm/db/queryHBase.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/03/09 3 | # @Author : Leo Zhang 4 | # @File : queryHBase.py 5 | # ************************** 6 | import phoenixdb 7 | import phoenixdb.cursor 8 | from comm import * 9 | import logging 10 | 11 | 12 | class PhoenixServer(object): 13 | """ 14 | 封装HBase常用方法。 15 | """ 16 | def __init__(self, address): 17 | url = 'http://{}/'.format(address) 18 | logging.debug('Connect HBase: {}'.format(url)) 19 | try: 20 | self.conn = phoenixdb.connect(url, autocommit=True) 21 | except Exception as e: 22 | raise Exception('连接异常>>> {}'.format(e)) 23 | 24 | # 增加、修改、删除命令语句 25 | def execute(self, sql): 26 | try: 27 | # 创建游标 28 | cursor = self.conn.cursor(cursor_factory=phoenixdb.cursor.Cursor) 29 | # 执行sql语句 30 | cursor.execute(sql) 31 | # 关闭游标 32 | cursor.close() 33 | except Exception as e: 34 | raise Exception('执行异常>>> {}'.format(e)) 35 | 36 | # 查询所有数据,多个值 37 | def query(self, sql, is_dict): 38 | try: 39 | # 判断是否需要返回结果为字典类型 40 | if is_dict: 41 | cursor = self.conn.cursor(cursor_factory=phoenixdb.cursor.DictCursor) 42 | else: 43 | cursor = self.conn.cursor(cursor_factory=phoenixdb.cursor.Cursor) 44 | # 执行sql语句 45 | cursor.execute(sql) 46 | # 查询结果 47 | data = cursor.fetchall() 48 | # 关闭游标 49 | cursor.close() 50 | return data 51 | except Exception as e: 52 | raise Exception('查询异常>>> {}'.format(e)) 53 | 54 | # 关闭数据库连接 55 | def close(self): 56 | self.conn.close() 57 | -------------------------------------------------------------------------------- /PyDemo/report/html/plugins/packages/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | allure.api.addTranslation('en', { 4 | tab: { 5 | packages: { 6 | name: 'Packages' 7 | } 8 | } 9 | }); 10 | 11 | allure.api.addTranslation('ru', { 12 | tab: { 13 | packages: { 14 | name: 'Пакеты' 15 | } 16 | } 17 | }); 18 | 19 | allure.api.addTranslation('zh', { 20 | tab: { 21 | packages: { 22 | name: '包' 23 | } 24 | } 25 | }); 26 | 27 | allure.api.addTranslation('de', { 28 | tab: { 29 | packages: { 30 | name: 'Pakete' 31 | } 32 | } 33 | }); 34 | 35 | allure.api.addTranslation('he', { 36 | tab: { 37 | packages: { 38 | name: 'חבילות' 39 | } 40 | } 41 | }); 42 | 43 | allure.api.addTranslation('br', { 44 | tab: { 45 | packages: { 46 | name: 'Pacotes' 47 | } 48 | } 49 | }); 50 | 51 | allure.api.addTranslation('ja', { 52 | tab: { 53 | packages: { 54 | name: 'パッケージ' 55 | } 56 | } 57 | }); 58 | 59 | allure.api.addTranslation('es', { 60 | tab: { 61 | packages: { 62 | name: 'Paquetes' 63 | } 64 | } 65 | }); 66 | 67 | allure.api.addTranslation('kr', { 68 | tab: { 69 | packages: { 70 | name: '패키지' 71 | } 72 | } 73 | }); 74 | 75 | allure.api.addTab('packages', { 76 | title: 'tab.packages.name', icon: 'fa fa-align-left', 77 | route: 'packages(/)(:testGroup)(/)(:testResult)(/)(:testResultTab)(/)', 78 | onEnter: (function (testGroup, testResult, testResultTab) { 79 | return new allure.components.TreeLayout({ 80 | testGroup: testGroup, 81 | testResult: testResult, 82 | testResultTab: testResultTab, 83 | tabName: 'tab.packages.name', 84 | baseUrl: 'packages', 85 | url: 'data/packages.json' 86 | }); 87 | }) 88 | }); 89 | -------------------------------------------------------------------------------- /comm/utils/readConf.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2020/12/03 3 | # @Author : Leo Zhang 4 | # @File : readConf.py 5 | # *********************** 6 | import codecs 7 | import configparser 8 | 9 | 10 | class ReadConf: 11 | 12 | def __init__(self, cfg_path): 13 | """ 14 | 配置文件初始化 15 | :param cfg_path: 16 | """ 17 | fd = open(cfg_path.replace('\\', '/'), encoding='utf-8') 18 | data = fd.read() 19 | # 去除配置文件开头编码标识 20 | if data[:3] == codecs.BOM_UTF8: 21 | data = data[3:] 22 | files = codecs.open(cfg_path, "w") 23 | files.write(data) 24 | files.close() 25 | fd.close() 26 | self.cf = configparser.ConfigParser() 27 | self.cf.read(cfg_path, encoding='utf-8-sig') 28 | 29 | def get_sections(self): 30 | """ 31 | 获取所有条目 32 | :return: 33 | """ 34 | return self.cf.sections() 35 | 36 | def get_items(self, section): 37 | """ 38 | 获取指定条目下所有键值对 39 | :param section: 40 | :return: 41 | """ 42 | return self.cf.items(section) 43 | 44 | def get_options(self, section): 45 | """ 46 | 获取指定条目下所有键值 47 | :param section: 48 | :return: 49 | """ 50 | return self.cf.options(section) 51 | 52 | def get_value(self, section, option): 53 | """ 54 | 获取指定条目指定键的值 55 | :param section: 56 | :param option: 57 | :return: 58 | """ 59 | return self.cf.get(section, option) 60 | 61 | def has_section(self, section): 62 | """ 63 | 返回是否存在指定条目 64 | :param section: 65 | :return: 66 | """ 67 | return self.cf.has_section(section) 68 | 69 | def has_option(self, section, option): 70 | """ 71 | 返回指定条目是否存在指定键 72 | :param section: 73 | :param option: 74 | :return: 75 | """ 76 | return self.cf.has_option(section, option) 77 | -------------------------------------------------------------------------------- /PyDemo/report/html/history/history.json: -------------------------------------------------------------------------------- 1 | { 2 | "fb868315583aa11e2cd2b0339b92f05a" : { 3 | "statistic" : { 4 | "failed" : 0, 5 | "broken" : 1, 6 | "skipped" : 0, 7 | "passed" : 0, 8 | "unknown" : 0, 9 | "total" : 1 10 | }, 11 | "items" : [ { 12 | "uid" : "e5c5230705b9bfbb", 13 | "status" : "broken", 14 | "statusDetails" : "Exception: JSON格式校验,关键字 success 返回结果 True 与期望结果 None 类型不符", 15 | "time" : { 16 | "start" : 1612427966998, 17 | "stop" : 1612427969076, 18 | "duration" : 2078 19 | } 20 | } ] 21 | }, 22 | "27801e67fb61317f40b6cdc1f8d317aa" : { 23 | "statistic" : { 24 | "failed" : 0, 25 | "broken" : 0, 26 | "skipped" : 0, 27 | "passed" : 1, 28 | "unknown" : 0, 29 | "total" : 1 30 | }, 31 | "items" : [ { 32 | "uid" : "7d4ed4f7a18b20d4", 33 | "status" : "passed", 34 | "time" : { 35 | "start" : 1612427970157, 36 | "stop" : 1612427971195, 37 | "duration" : 1038 38 | } 39 | } ] 40 | }, 41 | "62cffe5b54c1489b5c40af1b7f11c19b" : { 42 | "statistic" : { 43 | "failed" : 0, 44 | "broken" : 0, 45 | "skipped" : 0, 46 | "passed" : 1, 47 | "unknown" : 0, 48 | "total" : 1 49 | }, 50 | "items" : [ { 51 | "uid" : "10d4bd6301177f6", 52 | "status" : "passed", 53 | "time" : { 54 | "start" : 1612427969141, 55 | "stop" : 1612427970154, 56 | "duration" : 1013 57 | } 58 | } ] 59 | }, 60 | "1155f03dcf38b2069e797022e1f66d78" : { 61 | "statistic" : { 62 | "failed" : 0, 63 | "broken" : 0, 64 | "skipped" : 0, 65 | "passed" : 1, 66 | "unknown" : 0, 67 | "total" : 1 68 | }, 69 | "items" : [ { 70 | "uid" : "aa8dfcaa510813c2", 71 | "status" : "passed", 72 | "time" : { 73 | "start" : 1612427971198, 74 | "stop" : 1612427972269, 75 | "duration" : 1071 76 | } 77 | } ] 78 | } 79 | } -------------------------------------------------------------------------------- /comm/db/querySolr.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/03/12 3 | # @Author : Leo Zhang 4 | # @File : querySolr.py 5 | # ************************* 6 | import pysolr 7 | import logging 8 | import re 9 | 10 | 11 | def search_solr(address, sql): 12 | """获取Solr数据 13 | 14 | :param address: 地址(格式:ip:port) 15 | :param sql: sql查询语句 16 | :return: 17 | """ 18 | # 检索SQL语句 19 | exp = r"^select (.*?) from (.*?) where (.*?)$" 20 | res = re.findall(exp, sql.strip()) 21 | fields, db, conditions = res[0] 22 | 23 | # 重新拼接查询条件 24 | query = '' 25 | for each in conditions.split(' and '): 26 | key, value = each.replace('\'', '').replace('\"', '').split('=') 27 | if query: 28 | query += '&& ' 29 | query += '{}:"{}" '.format(key, value) 30 | 31 | # 初始化Solr 32 | try: 33 | base_url = 'http://{0}/solr/{1}/'.format(address, db) 34 | solr = pysolr.Solr(base_url) 35 | except Exception as e: 36 | raise Exception('连接异常>>> \n{}'.format(e)) 37 | 38 | # 执行查询 39 | query_str = 'GET {0}select?q={1}'.format(base_url, query) 40 | logging.info('执行查询>>> {}'.format(query_str)) 41 | try: 42 | data = solr.search(query) 43 | result = list() 44 | for each in data: 45 | result.append(each) 46 | if result: 47 | # 判断是否返回全部字段 48 | if fields == '*': 49 | return result 50 | else: 51 | # 返回指定字段 52 | result_new = list() 53 | for res in result: 54 | line = dict() 55 | for each in fields.split(','): 56 | try: 57 | line[each] = res[each] 58 | except KeyError: 59 | raise KeyError('Solr未知字段>>> {}'.format(each)) 60 | result_new.append(result) 61 | return result_new 62 | except Exception as e: 63 | raise Exception('查询异常>>> \n{}'.format(e)) 64 | -------------------------------------------------------------------------------- /comm/db/queryMysql.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/03/09 3 | # @Author : Leo Zhang 4 | # @File : queryMysql.py 5 | # ************************** 6 | import pymysql 7 | import logging 8 | 9 | 10 | class MysqlServer: 11 | """ 12 | 封装MySQL常用方法。 13 | """ 14 | def __init__(self, host, port, db, user, passwd, charset='utf8'): 15 | # 初始化数据库 16 | logging.debug('Connect MySQL: host={host}, port={port}, db={db}, user={user}, passwd={passwd}' 17 | .format(host=host, port=port, db=db, user=user, passwd=passwd)) 18 | try: 19 | self.conn = pymysql.connect(host=host, port=port, db=db, user=user, passwd=passwd, charset=charset) 20 | except Exception as e: 21 | raise Exception('连接异常>>> {}'.format(e)) 22 | 23 | # 增加、修改、删除命令语句 24 | def execute(self, sql): 25 | try: 26 | # 创建游标 27 | cur = self.conn.cursor(cursor=pymysql.cursors.Cursor) 28 | # 执行sql语句 29 | cur.execute(sql) 30 | # 提交事务 31 | self.conn.commit() 32 | # 关闭游标 33 | cur.close() 34 | except Exception as e: 35 | # 出错时回滚 36 | self.conn.rollback() 37 | raise Exception('执行异常>>> {}'.format(e)) 38 | 39 | # 查询所有数据,多个值 40 | def query(self, sql, is_dict): 41 | try: 42 | # 检查当前连接是否已关闭并进行重接 43 | self.conn.ping(reconnect=True) 44 | # 判断是否需要返回结果为字典类型 45 | if is_dict: 46 | cur = self.conn.cursor(cursor=pymysql.cursors.DictCursor) 47 | else: 48 | cur = self.conn.cursor(cursor=pymysql.cursors.Cursor) 49 | # 执行sql语句 50 | cur.execute(sql) 51 | # 查询结果 52 | data = cur.fetchall() 53 | # 关闭游标 54 | cur.close() 55 | return data 56 | except Exception as e: 57 | raise Exception('查询异常>>> {}'.format(e)) 58 | 59 | # 关闭数据库连接 60 | def close(self): 61 | self.conn.close() 62 | -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/64a95aad22c4bff3.txt: -------------------------------------------------------------------------------- 1 | DEBUG root:initializePremise.py:53 测试信息处理结果:{'title': 'register', 'host': '10.88.88.141:20037', 'scheme': 'http', 'method': 'POST', 'address': '/api/register/findParam', 'mime_type': 'application/x-www-form-urlencoded', 'headers': {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'}, 'timeout': 10, 'file': False, 'cookies': False, 'premise': False} 2 | DEBUG root:initializePremise.py:116 请求参数处理结果:{'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} 3 | DEBUG root:readRelevance.py:45 获取关联键列表: 4 | [] 5 | DEBUG root:initializePremise.py:123 期望返回处理结果:{'summary': 'findParam', 'describe': 'test_findParam', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}}} 6 | INFO root:apiSend.py:37 ====================================================================================================================================================== 7 | INFO root:apiSend.py:38 请求接口:findParam 8 | INFO root:apiSend.py:39 请求地址:http://10.88.88.141:20037/api/register/findParam 9 | INFO root:apiSend.py:40 请求头: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} 10 | INFO root:apiSend.py:41 请求参数: {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} 11 | INFO root:apiSend.py:58 请求方法: POST 12 | DEBUG urllib3.connectionpool:connectionpool.py:206 Starting new HTTP connection (1): 10.88.88.141:20037 13 | DEBUG urllib3.connectionpool:connectionpool.py:396 http://10.88.88.141:20037 "POST /api/register/findParam HTTP/1.1" 200 82 14 | INFO root:apiSend.py:137 请求接口结果: 15 | (200, {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}) -------------------------------------------------------------------------------- /PyDemo/report/xml/d1e7014d-1938-42c6-a229-2aa35065f3f6-attachment.txt: -------------------------------------------------------------------------------- 1 | DEBUG root:initializePremise.py:53 测试信息处理结果:{'title': 'register', 'host': '10.88.88.141:20037', 'scheme': 'http', 'method': 'POST', 'address': '/api/register/findParam', 'mime_type': 'application/x-www-form-urlencoded', 'headers': {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'}, 'timeout': 10, 'file': False, 'cookies': False, 'premise': False} 2 | DEBUG root:initializePremise.py:116 请求参数处理结果:{'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} 3 | DEBUG root:readRelevance.py:45 获取关联键列表: 4 | [] 5 | DEBUG root:initializePremise.py:123 期望返回处理结果:{'summary': 'findParam', 'describe': 'test_findParam', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}}} 6 | INFO root:apiSend.py:37 ====================================================================================================================================================== 7 | INFO root:apiSend.py:38 请求接口:findParam 8 | INFO root:apiSend.py:39 请求地址:http://10.88.88.141:20037/api/register/findParam 9 | INFO root:apiSend.py:40 请求头: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'} 10 | INFO root:apiSend.py:41 请求参数: {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg='} 11 | INFO root:apiSend.py:58 请求方法: POST 12 | DEBUG urllib3.connectionpool:connectionpool.py:206 Starting new HTTP connection (1): 10.88.88.141:20037 13 | DEBUG urllib3.connectionpool:connectionpool.py:396 http://10.88.88.141:20037 "POST /api/register/findParam HTTP/1.1" 200 82 14 | INFO root:apiSend.py:137 请求接口结果: 15 | (200, {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}) -------------------------------------------------------------------------------- /PyDemo/report/xml/21ed8173-cd5d-4d38-95f1-29ba7ef35c26-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_initCanSelInfo[case_data0]", "status": "passed", "steps": [{"name": "POST请求接口", "status": "passed", "attachments": [{"name": "请求接口", "source": "b6a76b88-e182-454b-ba36-1e34a5c19222-attachment.attach"}, {"name": "请求地址", "source": "194b21ff-bc74-4712-9e00-2d4d10c529f3-attachment.attach"}, {"name": "请求头", "source": "4f67b9c3-4ae0-4945-9697-c30b6dbbcbf0-attachment.attach"}, {"name": "请求参数", "source": "ae13f7d4-0fd7-42fd-b524-ac0e2af5718a-attachment.attach"}], "start": 1612427971221, "stop": 1612427971223}, {"name": "JSON格式校验结果", "status": "passed", "attachments": [{"name": "实际code", "source": "c5f832b3-c5da-4106-8a5d-8bc617600550-attachment.attach"}, {"name": "期望code", "source": "33849d22-c42b-4fd4-b486-acfe3922e91a-attachment.attach"}, {"name": "实际data", "source": "65b6cc0f-13d5-49c6-be30-e0758d61e2ee-attachment.attach"}, {"name": "期望data", "source": "8d2bd0b1-dc2f-4ea3-ac47-0db1b631d087-attachment.attach"}], "start": 1612427972266, "stop": 1612427972269}], "attachments": [{"name": "log", "source": "f48ca424-0649-43d3-b8ba-5d91599e129a-attachment.txt", "type": "text/plain"}], "parameters": [{"name": "case_data", "value": "{'summary': 'initCanSelInfo', 'describe': 'test_initCanSelInfo', 'parameter': 'initCanSelInfo_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'initCanSelInfo_response.json'}}"}], "start": 1612427971198, "stop": 1612427972269, "uuid": "6532a322-3db7-49e2-82cc-e07ece13c849", "historyId": "1155f03dcf38b2069e797022e1f66d78", "testCaseId": "98b2b28a5672b7ba7f61a8bc99cb4083", "fullName": "PyDemo.testcase.register.test_initCanSelInfo.TestRegister#test_initCanSelInfo", "labels": [{"name": "story", "value": "test_initCanSelInfo"}, {"name": "feature", "value": "register"}, {"name": "parentSuite", "value": "PyDemo.testcase.register"}, {"name": "suite", "value": "test_initCanSelInfo"}, {"name": "subSuite", "value": "TestRegister"}, {"name": "host", "value": "Leo-PC"}, {"name": "thread", "value": "1096-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "PyDemo.testcase.register.test_initCanSelInfo"}]} -------------------------------------------------------------------------------- /comm/db/queryES.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/03/09 3 | # @Author : Leo Zhang 4 | # @File : queryES.py 5 | # ************************** 6 | import elasticsearch 7 | import logging 8 | import re 9 | 10 | 11 | def elastic_search(address, db, sql): 12 | """获取ElasticSearch数据 13 | 14 | :param address: ES地址(格式:ip:port) 15 | :param db: 索引库名 16 | :param sql: sql查询语句 17 | :return: 18 | """ 19 | # 初始化ES 20 | try: 21 | es = elasticsearch.Elasticsearch([address]) 22 | except Exception as e: 23 | raise Exception('连接异常>>> \n{}'.format(e)) 24 | 25 | # 检索SQL语句 26 | exp = r"^select (.*?) from (.*?) where (.*?)$" 27 | res = re.findall(exp, sql.strip()) 28 | fields, table, conditions = res[0] 29 | # 重新拼接查询条件 30 | query = '' 31 | for each in conditions.split(' and '): 32 | key, value = each.replace('\'', '').replace('\"', '').split('=') 33 | if query: 34 | query += '&& ' 35 | query += '{}:"{}" '.format(key, value) 36 | 37 | # 执行查询 38 | db_table = db + '@' + table 39 | # query_str = 'GET http://{0}/{1}/_search?q={2}'.format(address, db_table, query) 40 | # logging.info('执行查询>>> {}'.format(query_str)) 41 | try: 42 | # 查询ES,并截取hits字段 43 | data = es.search(index=db_table, q=query) 44 | hits = data['hits']['hits'] 45 | if hits: 46 | # 截取字段值_source 47 | new_hits = list() 48 | for hit in hits: 49 | new_hits.append(hit['_source']) 50 | # 判断是否返回全部字段 51 | if fields == '*': 52 | return new_hits 53 | else: 54 | # 返回指定字段 55 | source_new = list() 56 | for hit in new_hits: 57 | result = dict() 58 | for each in fields.split(','): 59 | try: 60 | result[each] = hit[each] 61 | except KeyError: 62 | raise KeyError('ES未知字段>>> {}'.format(each)) 63 | source_new.append(result) 64 | return source_new 65 | except Exception as e: 66 | raise Exception('查询异常>>> \n{}'.format(e)) 67 | -------------------------------------------------------------------------------- /PyDemo/report/xml/63c03902-4149-4b77-8334-25a617516bde-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_findParam[case_data0]", "status": "passed", "steps": [{"name": "POST请求接口", "status": "passed", "attachments": [{"name": "请求接口", "source": "9487b1b8-64e5-49d0-a0ea-f2254a0a983f-attachment.attach"}, {"name": "请求地址", "source": "d354f47a-3693-4b7b-86df-cd34ace4ac9c-attachment.attach"}, {"name": "请求头", "source": "7c22884c-0191-4937-b2d2-12214a869f4c-attachment.attach"}, {"name": "请求参数", "source": "0d998249-b346-4cb4-a883-985eb7fbd7a1-attachment.attach"}], "start": 1612427969143, "stop": 1612427969144}, {"name": "JSON格式校验结果", "status": "passed", "attachments": [{"name": "实际code", "source": "30403406-d497-4fa4-8a90-e52a5f1723aa-attachment.attach"}, {"name": "期望code", "source": "a925524d-3c79-42dc-a506-ac9353b81a89-attachment.attach"}, {"name": "实际data", "source": "6bc3acef-572c-47fe-9093-56a69faa51ed-attachment.attach"}, {"name": "期望data", "source": "bc8c8933-6042-4cfe-a825-a19018c34101-attachment.attach"}], "start": 1612427970152, "stop": 1612427970154}], "attachments": [{"name": "log", "source": "d1e7014d-1938-42c6-a229-2aa35065f3f6-attachment.txt", "type": "text/plain"}], "parameters": [{"name": "case_data", "value": "{'summary': 'findParam', 'describe': 'test_findParam', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}}}"}], "start": 1612427969141, "stop": 1612427970154, "uuid": "3d9d32a9-9cdb-4de9-860f-97593382fd4d", "historyId": "62cffe5b54c1489b5c40af1b7f11c19b", "testCaseId": "039a4a0201219a85366197a1924a467a", "fullName": "PyDemo.testcase.register.test_findParam.TestRegister#test_findParam", "labels": [{"name": "story", "value": "test_findParam"}, {"name": "feature", "value": "register"}, {"name": "parentSuite", "value": "PyDemo.testcase.register"}, {"name": "suite", "value": "test_findParam"}, {"name": "subSuite", "value": "TestRegister"}, {"name": "host", "value": "Leo-PC"}, {"name": "thread", "value": "1096-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "PyDemo.testcase.register.test_findParam"}]} -------------------------------------------------------------------------------- /PyDemo/report/xml/dae24e92-696a-4d8a-a4a1-d453299da76d-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_getAdultCurbactList[case_data0]", "status": "passed", "steps": [{"name": "POST请求接口", "status": "passed", "attachments": [{"name": "请求接口", "source": "f1dc7f0e-4445-425a-b4b7-f4b073d49233-attachment.attach"}, {"name": "请求地址", "source": "848e4b5e-7e91-4f72-874b-659053c3e48d-attachment.attach"}, {"name": "请求头", "source": "067d3035-4727-4009-af05-75776743f64e-attachment.attach"}, {"name": "请求参数", "source": "b3aaf70f-749f-450d-841f-18feaa49b10d-attachment.attach"}], "start": 1612427970161, "stop": 1612427970164}, {"name": "JSON格式校验结果", "status": "passed", "attachments": [{"name": "实际code", "source": "13581612-dbff-44e2-b614-28aeaf763e53-attachment.attach"}, {"name": "期望code", "source": "2d3cbb34-52fb-4b35-80e8-179d043a1226-attachment.attach"}, {"name": "实际data", "source": "a8105e8d-2465-4d01-9dca-cec2937a0cfd-attachment.attach"}, {"name": "期望data", "source": "11f08016-1abb-461e-9e6d-fe83310ea63b-attachment.attach"}], "start": 1612427971193, "stop": 1612427971195}], "attachments": [{"name": "log", "source": "53ee1c53-95a3-4472-bbc9-be8911c154a0-attachment.txt", "type": "text/plain"}], "parameters": [{"name": "case_data", "value": "{'summary': 'getAdultCurbactList', 'describe': 'test_getAdultCurbactList', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'getAdultCurbactList_response.json'}}"}], "start": 1612427970157, "stop": 1612427971195, "uuid": "27c2d884-886e-42a4-b1ca-34f6631a070c", "historyId": "27801e67fb61317f40b6cdc1f8d317aa", "testCaseId": "35e417966dd957c1f01ed34ddc30f12f", "fullName": "PyDemo.testcase.register.test_getAdultCurbactList.TestRegister#test_getAdultCurbactList", "labels": [{"name": "story", "value": "test_getAdultCurbactList"}, {"name": "feature", "value": "register"}, {"name": "parentSuite", "value": "PyDemo.testcase.register"}, {"name": "suite", "value": "test_getAdultCurbactList"}, {"name": "subSuite", "value": "TestRegister"}, {"name": "host", "value": "Leo-PC"}, {"name": "thread", "value": "1096-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "PyDemo.testcase.register.test_getAdultCurbactList"}]} -------------------------------------------------------------------------------- /PyDemo/data/findParam.chlsj: -------------------------------------------------------------------------------- 1 | [{"status":"COMPLETE","method":"POST","protocolVersion":"HTTP/1.1","scheme":"http","host":"127.0.0.1","port":20037,"actualPort":20037,"path":"/api/register/findParam","query":null,"tunnel":false,"keptAlive":false,"webSocket":false,"remoteAddress":"127.0.0.1/127.0.0.1","clientAddress":"/127.0.0.1","clientPort":59266,"times":{"start":"2021-02-04T08:35:25.301+08:00","requestBegin":"2021-02-04T08:35:25.303+08:00","requestComplete":"2021-02-04T08:35:25.303+08:00","responseBegin":"2021-02-04T08:35:25.318+08:00","end":"2021-02-04T08:35:25.319+08:00"},"durations":{"total":17,"dns":0,"connect":1,"ssl":null,"request":0,"response":1,"latency":15},"speeds":{"overall":"64294","request":"0","response":"476000"},"totalSize":"1093","request":{"sizes":{"headers":480,"body":137},"mimeType":"application/x-www-form-urlencoded","charset":"UTF-8","contentEncoding":null,"header":{"firstLine":"POST /api/register/findParam HTTP/1.1","headers":[{"name":"Host","value":"127.0.0.1:20037"},{"name":"Content-Length","value":"137"},{"name":"Accept","value":"application/json, text/plain, */*"},{"name":"User-Agent","value":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"},{"name":"Content-Type","value":"application/x-www-form-urlencoded;charset=UTF-8"},{"name":"Origin","value":"http://127.0.0.1:6006"},{"name":"Referer","value":"http://127.0.0.1:6006/"},{"name":"Accept-Encoding","value":"gzip, deflate"},{"name":"Accept-Language","value":"zh-CN,zh;q=0.9"},{"name":"Connection","value":"keep-alive"}]},"body":{"text":"{\"params\":{\"unitCode\":\"3202112002\",\"first\":0,\"pym\":\"\",\"pageSize\":10,\"page\":0},\"headtoken\":\"/8QPAj9LlNJ1MaPd9ykD9cHql4tf3Xw/fu+VnRGKtCw=\"}","charset":"UTF-8"}},"response":{"status":200,"sizes":{"headers":394,"body":82},"mimeType":"application/json","charset":"UTF-8","contentEncoding":null,"header":{"firstLine":"HTTP/1.1 200 ","headers":[{"name":"Server","value":"nginx/1.14.2"},{"name":"Date","value":"Thu, 04 Feb 2021 00:29:29 GMT"},{"name":"Content-Type","value":"application/json;charset=UTF-8"},{"name":"Content-Length","value":"82"},{"name":"Access-Control-Allow-Headers","value":"Content-Type,x-requested-with,Authorization,Access-Control-Allow-Origin"},{"name":"Access-Control-Allow-Methods","value":"POST, GET, OPTIONS"},{"name":"Access-Control-Allow-Origin","value":"*"},{"name":"Access-Control-Max-Age","value":"360"},{"name":"Proxy-Connection","value":"keep-alive"}]},"body":{"text":"{\"success\":true,\"code\":null,\"msg\":\"返回成功\",\"data\":[\"1\",\"1\"],\"callTime\":null}","charset":"UTF-8"}}}] -------------------------------------------------------------------------------- /comm/script/writeCase.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2020/10/15 3 | # @Author : Leo Zhang 4 | # @File : writeCase.py 5 | # ************************ 6 | import os 7 | from config import ROOT_DIR 8 | from comm.script.writeCaseYml import write_case_yaml, read_yaml_data 9 | temp_file = ROOT_DIR+'config/test_template.py' 10 | 11 | 12 | def write_case(case_path, auto_yaml=True): 13 | """ 14 | 15 | :param case_path: 用例路径,当auto_yaml为True时,需要传入data目录,否则传入扫描目录 16 | :param auto_yaml: 是否自动生成yaml文件 17 | :return: 18 | """ 19 | # 判断是否自动生成yaml用例 20 | if auto_yaml: 21 | yaml_list = write_case_yaml(case_path) 22 | else: 23 | yaml_list = list() 24 | file_list = os.listdir(case_path) 25 | for file in file_list: 26 | if '.yaml' in file: 27 | yaml_path = case_path+'/'+file 28 | yaml_list.append(yaml_path) 29 | 30 | # 遍历测试用例列表 31 | for yaml_file in yaml_list: 32 | test_data = read_yaml_data(yaml_file) 33 | test_script = yaml_file.replace('\\', '/').replace('/page/', '/testcase/').replace('.yaml', '.py') 34 | # case_name = os.path.basename(test_script).replace('.py', '') 35 | case_path = os.path.dirname(test_script) 36 | # 判断文件路径是否存在 37 | if not os.path.exists(case_path): 38 | os.makedirs(case_path) 39 | 40 | # 判断测试用例脚本是否存在 41 | if os.path.exists(test_script): 42 | continue 43 | 44 | # 替换模板内容 45 | file_data = '' 46 | with open(temp_file, "r", encoding="utf-8") as f: 47 | for line in f: 48 | if 'TestTemplate' in line: 49 | title = test_data['test_info']['title'] 50 | line = line.replace('Template', title.title()) 51 | if 'test_template' in line: 52 | if '@allure.story' in line: 53 | describe = test_data['test_case'][0]['describe'] 54 | line = line.replace('test_template', describe) 55 | else: 56 | summary = test_data['test_case'][0]['summary'] 57 | line = line.replace('template', summary) 58 | file_data += line 59 | 60 | # 写入新脚本 61 | with open(test_script, "w", encoding="utf-8") as f: 62 | f.write(file_data) 63 | 64 | 65 | if __name__ == '__main__': 66 | real_path = os.path.dirname(os.path.realpath(__file__)).replace('\\', '/') 67 | write_case(real_path + '/data', auto_yaml=True) 68 | # write_case(real_path+'/page/oauth', auto_yaml=False) 69 | -------------------------------------------------------------------------------- /PyDemo/data/addOrUpCurBact.chlsj: -------------------------------------------------------------------------------- 1 | [{"status":"COMPLETE","method":"POST","protocolVersion":"HTTP/1.1","scheme":"http","host":"127.0.0.1","port":20037,"actualPort":20037,"path":"/api/register/addOrUpCurBact","query":null,"tunnel":false,"keptAlive":true,"webSocket":false,"remoteAddress":"127.0.0.1/127.0.0.1","clientAddress":"/127.0.0.1","clientPort":59267,"times":{"start":"2021-02-04T08:35:57.615+08:00","requestBegin":"2021-02-04T08:35:57.616+08:00","requestComplete":"2021-02-04T08:35:57.617+08:00","responseBegin":"2021-02-04T08:35:57.636+08:00","end":"2021-02-04T08:35:57.637+08:00"},"durations":{"total":21,"dns":null,"connect":null,"ssl":null,"request":1,"response":1,"latency":19},"speeds":{"overall":"72809","request":"1058000","response":"471000"},"totalSize":"1529","request":{"sizes":{"headers":485,"body":573},"mimeType":"application/x-www-form-urlencoded","charset":"UTF-8","contentEncoding":null,"header":{"firstLine":"POST /api/register/addOrUpCurBact HTTP/1.1","headers":[{"name":"Host","value":"127.0.0.1:20037"},{"name":"Content-Length","value":"573"},{"name":"Accept","value":"application/json, text/plain, */*"},{"name":"User-Agent","value":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"},{"name":"Content-Type","value":"application/x-www-form-urlencoded;charset=UTF-8"},{"name":"Origin","value":"http://127.0.0.1:6006"},{"name":"Referer","value":"http://127.0.0.1:6006/"},{"name":"Accept-Encoding","value":"gzip, deflate"},{"name":"Accept-Language","value":"zh-CN,zh;q=0.9"},{"name":"Connection","value":"keep-alive"}]},"body":{"text":"{\"params\":{\"pageType\":\"0\",\"unitCode\":\"3202112002\",\"bactCode\":\"280101\",\"materType\":\"86901119000052\",\"coreName\":\"大连雅立峰\",\"corpSimpName\":\"大连雅立峰\",\"materName\":\"狂犬病疫苗(vero细胞)\",\"inocCorpCode\":\"50\",\"speCodeName\":\"1.0ml\",\"vaccSpeCode\":\"1002\",\"pym\":\"kqbymveroxb\",\"price\":\"0\",\"batnmb\":\"20110101\",\"qty\":\"100\",\"ifUse\":1,\"dataType\":2,\"createDate\":\"\",\"createManCode\":\"3202112002008\",\"modifyDate\":\"\",\"modifyManCode\":\"3202112002008\",\"bactValidate\":\"2022-02-02\",\"bizType\":1,\"materTypeCode\":\"1\"},\"headtoken\":\"/8QPAj9LlNJ1MaPd9ykD9cHql4tf3Xw/fu+VnRGKtCw=\"}","charset":"UTF-8"}},"response":{"status":200,"sizes":{"headers":394,"body":77},"mimeType":"application/json","charset":"UTF-8","contentEncoding":null,"header":{"firstLine":"HTTP/1.1 200 ","headers":[{"name":"Server","value":"nginx/1.14.2"},{"name":"Date","value":"Thu, 04 Feb 2021 00:30:02 GMT"},{"name":"Content-Type","value":"application/json;charset=UTF-8"},{"name":"Content-Length","value":"77"},{"name":"Access-Control-Allow-Headers","value":"Content-Type,x-requested-with,Authorization,Access-Control-Allow-Origin"},{"name":"Access-Control-Allow-Methods","value":"POST, GET, OPTIONS"},{"name":"Access-Control-Allow-Origin","value":"*"},{"name":"Access-Control-Max-Age","value":"360"},{"name":"Proxy-Connection","value":"keep-alive"}]},"body":{"text":"{\"success\":true,\"code\":null,\"msg\":\"返回成功\",\"data\":null,\"callTime\":null}","charset":"UTF-8"}}}] -------------------------------------------------------------------------------- /PyDemo/report/html/data/timeline.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid" : "ab17fc5a4eb3bca4b216b548c7f9fcbc", 3 | "name" : "timeline", 4 | "children" : [ { 5 | "name" : "Leo-PC", 6 | "children" : [ { 7 | "name" : "1096-MainThread", 8 | "children" : [ { 9 | "name" : "test_findParam[case_data0]", 10 | "uid" : "10d4bd6301177f6", 11 | "parentUid" : "0d5737b7c8f0eaf73ed6906fe9699a8a", 12 | "status" : "passed", 13 | "time" : { 14 | "start" : 1612427969141, 15 | "stop" : 1612427970154, 16 | "duration" : 1013 17 | }, 18 | "flaky" : false, 19 | "newFailed" : false, 20 | "parameters" : [ "{'summary': 'findParam', 'describe': 'test_findParam', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}}}" ] 21 | }, { 22 | "name" : "test_getAdultCurbactList[case_data0]", 23 | "uid" : "7d4ed4f7a18b20d4", 24 | "parentUid" : "0d5737b7c8f0eaf73ed6906fe9699a8a", 25 | "status" : "passed", 26 | "time" : { 27 | "start" : 1612427970157, 28 | "stop" : 1612427971195, 29 | "duration" : 1038 30 | }, 31 | "flaky" : false, 32 | "newFailed" : false, 33 | "parameters" : [ "{'summary': 'getAdultCurbactList', 'describe': 'test_getAdultCurbactList', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'getAdultCurbactList_response.json'}}" ] 34 | }, { 35 | "name" : "test_addOrUpCurBact[case_data0]", 36 | "uid" : "e5c5230705b9bfbb", 37 | "parentUid" : "0d5737b7c8f0eaf73ed6906fe9699a8a", 38 | "status" : "broken", 39 | "time" : { 40 | "start" : 1612427966998, 41 | "stop" : 1612427969076, 42 | "duration" : 2078 43 | }, 44 | "flaky" : false, 45 | "newFailed" : false, 46 | "parameters" : [ "{'summary': 'addOrUpCurBact', 'describe': 'test_addOrUpCurBact', 'parameter': 'addOrUpCurBact_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': None, 'callTime': None}}}" ] 47 | }, { 48 | "name" : "test_initCanSelInfo[case_data0]", 49 | "uid" : "aa8dfcaa510813c2", 50 | "parentUid" : "0d5737b7c8f0eaf73ed6906fe9699a8a", 51 | "status" : "passed", 52 | "time" : { 53 | "start" : 1612427971198, 54 | "stop" : 1612427972269, 55 | "duration" : 1071 56 | }, 57 | "flaky" : false, 58 | "newFailed" : false, 59 | "parameters" : [ "{'summary': 'initCanSelInfo', 'describe': 'test_initCanSelInfo', 'parameter': 'initCanSelInfo_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'initCanSelInfo_response.json'}}" ] 60 | } ], 61 | "uid" : "0d5737b7c8f0eaf73ed6906fe9699a8a" 62 | } ], 63 | "uid" : "29b2e37a8b2066a33626759906f3f57f" 64 | } ] 65 | } -------------------------------------------------------------------------------- /comm/unit/readRelevance.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/1/8 3 | # @Author : Leo Zhang 4 | # @File : readRelevance.py 5 | # **************************** 6 | import logging 7 | import re 8 | 9 | # __relevance = "" 10 | __relevance = [] 11 | 12 | 13 | def get_value(data, value): 14 | """获取数据中的值 15 | 16 | :param data: 17 | :param value: 18 | :return: 19 | """ 20 | global __relevance 21 | if isinstance(data, dict): 22 | # if value in data: 23 | # __relevance = data[value] 24 | # else: 25 | # for key in data: 26 | # __relevance = get_value(data[key], value) 27 | for key in data: 28 | if isinstance(data[key], dict): 29 | get_value(data[key], value) 30 | elif isinstance(data[key], list): 31 | for each in data[key]: 32 | if isinstance(each, dict): 33 | get_value(each, value) 34 | # for each in data[key]: 35 | # if isinstance(each, dict): 36 | # break 37 | else: 38 | if key == value: 39 | __relevance.append(data[key]) 40 | else: 41 | if key == value: 42 | __relevance.append(data[key]) 43 | elif isinstance(data, list): 44 | for key in data: 45 | if isinstance(key, dict): 46 | # __relevance = get_value(key, value) 47 | # break 48 | get_value(key, value) 49 | return __relevance 50 | 51 | 52 | def get_relevance(data, relevance_list, relevance=None): 53 | """获取关联键值对 54 | 55 | :param data: 56 | :param relevance_list: 57 | :param relevance: 58 | :return: 59 | """ 60 | global __relevance 61 | # 获取关联键列表 62 | relevance_list = re.findall(r"\${(.*?)}", str(relevance_list)) 63 | 64 | # 去除参数[n]标识 65 | for index, value in enumerate(relevance_list): 66 | mark = re.findall(r"\[\-?[0-9]*\]", value) 67 | # if mark: 68 | # relevance_list[index] = value.strip(mark[0]) 69 | for m in mark: 70 | value = value.replace(m, '') 71 | relevance_list[index] = value 72 | 73 | # 去除重复参数 74 | relevance_list = list(set(relevance_list)) 75 | logging.debug("获取关联键列表:\n%s" % relevance_list) 76 | 77 | # 判断关联键和源数据是否有值 78 | if (not data) or (not relevance_list): 79 | return relevance 80 | 81 | # 判断是否存在其他关联键对象 82 | if not relevance: 83 | relevance = dict() 84 | 85 | # 遍历关联键 86 | for each in relevance_list: 87 | # 只考虑一个关联键一个值 88 | # if each in relevance: 89 | # pass 90 | # else: 91 | # # 从结果中提取关联键的值 92 | # relevance[each] = get_value(data, each) 93 | 94 | # 考虑到一个关联键多个值 95 | relevance_value = get_value(data, each) 96 | if relevance_value: 97 | if each in relevance: 98 | tmp = relevance[each] 99 | if isinstance(tmp, list): 100 | tmp += relevance_value 101 | relevance[each] = tmp 102 | else: 103 | tmp2 = relevance_value.insert(0, tmp) 104 | relevance[each] = tmp2 105 | else: 106 | relevance[each] = relevance_value 107 | __relevance = [] 108 | logging.debug("提取关联键对象:\n%s" % relevance) 109 | return relevance 110 | -------------------------------------------------------------------------------- /comm/unit/queryDatabase.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/03/09 3 | # @Author : Leo Zhang 4 | # @File : queryDatabase.py 5 | # ************************** 6 | from comm.utils.readYaml import read_yaml_data 7 | from config import DB_CONFIG, PROJECT_NAME 8 | from comm.db import * 9 | import logging 10 | import time 11 | import re 12 | 13 | dbcfg = read_yaml_data(DB_CONFIG)[PROJECT_NAME] 14 | 15 | 16 | def query_mysql(sql): 17 | """查询MySQL数据 18 | 19 | :param sql: sql查询语句 20 | :return: 21 | """ 22 | # 获取配置信息 23 | timeout = dbcfg['timeout'] 24 | address = dbcfg['mysql_info']['address'] 25 | user = dbcfg['mysql_info']['user'] 26 | auth = dbcfg['mysql_info']['auth'] 27 | db = dbcfg['mysql_info']['db'] 28 | # 初始化MySQL 29 | host, port = address.split(':') 30 | mysql = MysqlServer(host, int(port), db, user, auth) 31 | logging.info('执行查询>>> {}'.format(sql)) 32 | # 循环查询 33 | for i in range(int(timeout)): 34 | try: 35 | result = mysql.query(sql, is_dict=True) 36 | mysql.close() 37 | if result: 38 | return result 39 | else: 40 | time.sleep(1) 41 | except Exception as e: 42 | raise Exception('查询异常>>> {}'.format(e)) 43 | else: 44 | return [] 45 | 46 | 47 | def query_hbase(sql): 48 | """查询HBase数据 49 | 50 | :param sql: sql查询语句 51 | :return: 52 | """ 53 | # 获取配置信息 54 | timeout = dbcfg['timeout'] 55 | address = dbcfg['hbase_info']['address'] 56 | db = dbcfg['hbase_info']['db'] 57 | # 检索SQL语句 58 | exp = r"^select .*? from (.*?) where .*?$" 59 | table = re.findall(exp, sql.strip())[0] 60 | # 添加数据库 61 | if '.' not in table: 62 | sql = sql.strip().replace(table, db+'.'+table) 63 | # 初始化HBase 64 | hbase = PhoenixServer(address) 65 | logging.info('执行查询>>> {}'.format(sql)) 66 | # 循环查询 67 | for i in range(int(timeout)): 68 | try: 69 | result = hbase.query(sql, is_dict=True) 70 | if result: 71 | return result 72 | else: 73 | time.sleep(1) 74 | except Exception as e: 75 | raise Exception('查询异常>>> {}'.format(e)) 76 | else: 77 | return [] 78 | 79 | 80 | def query_es(sql): 81 | """查询ES数据 82 | 83 | :param sql: sql查询语句 84 | :return: 85 | """ 86 | # 获取配置信息 87 | timeout = dbcfg['timeout'] 88 | address = dbcfg['es_info']['address'] 89 | db = dbcfg['es_info']['db'] 90 | logging.info('执行查询>>> {}'.format(sql)) 91 | # 循环查询 92 | for i in range(int(timeout)): 93 | try: 94 | result = elastic_search(address, db, sql) 95 | if result: 96 | return result 97 | else: 98 | time.sleep(1) 99 | except Exception as e: 100 | raise Exception('查询异常>>> {}'.format(e)) 101 | else: 102 | return [] 103 | 104 | 105 | def query_solr(sql): 106 | """查询solr数据 107 | 108 | :param sql: sql查询语句 109 | :return: 110 | """ 111 | # 获取配置信息 112 | timeout = dbcfg['timeout'] 113 | address = dbcfg['solr_info']['address'] 114 | logging.info('执行查询>>> {}'.format(sql)) 115 | # 循环查询 116 | for i in range(int(timeout)): 117 | try: 118 | result = search_solr(address, sql) 119 | if result: 120 | return result 121 | else: 122 | time.sleep(1) 123 | except Exception as e: 124 | raise Exception('查询异常>>> {}'.format(e)) 125 | else: 126 | return [] 127 | -------------------------------------------------------------------------------- /PyDemo/report/html/data/behaviors.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid" : "b1a8273437954620fa374b796ffaacdd", 3 | "name" : "behaviors", 4 | "children" : [ { 5 | "name" : "register", 6 | "children" : [ { 7 | "name" : "test_addOrUpCurBact", 8 | "children" : [ { 9 | "name" : "test_addOrUpCurBact[case_data0]", 10 | "uid" : "e5c5230705b9bfbb", 11 | "parentUid" : "d566fe8071743e379fe2d541eff0a459", 12 | "status" : "broken", 13 | "time" : { 14 | "start" : 1612427966998, 15 | "stop" : 1612427969076, 16 | "duration" : 2078 17 | }, 18 | "flaky" : false, 19 | "newFailed" : false, 20 | "parameters" : [ "{'summary': 'addOrUpCurBact', 'describe': 'test_addOrUpCurBact', 'parameter': 'addOrUpCurBact_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': None, 'callTime': None}}}" ] 21 | } ], 22 | "uid" : "d566fe8071743e379fe2d541eff0a459" 23 | }, { 24 | "name" : "test_findParam", 25 | "children" : [ { 26 | "name" : "test_findParam[case_data0]", 27 | "uid" : "10d4bd6301177f6", 28 | "parentUid" : "6499da8712dcd7b54b556fa696d8c606", 29 | "status" : "passed", 30 | "time" : { 31 | "start" : 1612427969141, 32 | "stop" : 1612427970154, 33 | "duration" : 1013 34 | }, 35 | "flaky" : false, 36 | "newFailed" : false, 37 | "parameters" : [ "{'summary': 'findParam', 'describe': 'test_findParam', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}}}" ] 38 | } ], 39 | "uid" : "6499da8712dcd7b54b556fa696d8c606" 40 | }, { 41 | "name" : "test_getAdultCurbactList", 42 | "children" : [ { 43 | "name" : "test_getAdultCurbactList[case_data0]", 44 | "uid" : "7d4ed4f7a18b20d4", 45 | "parentUid" : "ec5dd644558c5ede81175da3d69997c9", 46 | "status" : "passed", 47 | "time" : { 48 | "start" : 1612427970157, 49 | "stop" : 1612427971195, 50 | "duration" : 1038 51 | }, 52 | "flaky" : false, 53 | "newFailed" : false, 54 | "parameters" : [ "{'summary': 'getAdultCurbactList', 'describe': 'test_getAdultCurbactList', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'getAdultCurbactList_response.json'}}" ] 55 | } ], 56 | "uid" : "ec5dd644558c5ede81175da3d69997c9" 57 | }, { 58 | "name" : "test_initCanSelInfo", 59 | "children" : [ { 60 | "name" : "test_initCanSelInfo[case_data0]", 61 | "uid" : "aa8dfcaa510813c2", 62 | "parentUid" : "d2c6018092b62680c13e6aea19af3982", 63 | "status" : "passed", 64 | "time" : { 65 | "start" : 1612427971198, 66 | "stop" : 1612427972269, 67 | "duration" : 1071 68 | }, 69 | "flaky" : false, 70 | "newFailed" : false, 71 | "parameters" : [ "{'summary': 'initCanSelInfo', 'describe': 'test_initCanSelInfo', 'parameter': 'initCanSelInfo_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'initCanSelInfo_response.json'}}" ] 72 | } ], 73 | "uid" : "d2c6018092b62680c13e6aea19af3982" 74 | } ], 75 | "uid" : "f9614baa9d268c2fa96855398ce8a7bf" 76 | } ] 77 | } -------------------------------------------------------------------------------- /PyDemo/report/html/data/packages.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid" : "83edc06c07f9ae9e47eb6dd1b683e4e2", 3 | "name" : "packages", 4 | "children" : [ { 5 | "name" : "PyDemo.testcase.register", 6 | "children" : [ { 7 | "name" : "test_addOrUpCurBact", 8 | "children" : [ { 9 | "name" : "test_addOrUpCurBact[case_data0]", 10 | "uid" : "e5c5230705b9bfbb", 11 | "parentUid" : "f153e80a6e9389222095044a1da3521a", 12 | "status" : "broken", 13 | "time" : { 14 | "start" : 1612427966998, 15 | "stop" : 1612427969076, 16 | "duration" : 2078 17 | }, 18 | "flaky" : false, 19 | "newFailed" : false, 20 | "parameters" : [ "{'summary': 'addOrUpCurBact', 'describe': 'test_addOrUpCurBact', 'parameter': 'addOrUpCurBact_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': None, 'callTime': None}}}" ] 21 | } ], 22 | "uid" : "f153e80a6e9389222095044a1da3521a" 23 | }, { 24 | "name" : "test_findParam", 25 | "children" : [ { 26 | "name" : "test_findParam[case_data0]", 27 | "uid" : "10d4bd6301177f6", 28 | "parentUid" : "f5cbb0f92dea3d0ffa74221d10e6ba6e", 29 | "status" : "passed", 30 | "time" : { 31 | "start" : 1612427969141, 32 | "stop" : 1612427970154, 33 | "duration" : 1013 34 | }, 35 | "flaky" : false, 36 | "newFailed" : false, 37 | "parameters" : [ "{'summary': 'findParam', 'describe': 'test_findParam', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}}}" ] 38 | } ], 39 | "uid" : "f5cbb0f92dea3d0ffa74221d10e6ba6e" 40 | }, { 41 | "name" : "test_getAdultCurbactList", 42 | "children" : [ { 43 | "name" : "test_getAdultCurbactList[case_data0]", 44 | "uid" : "7d4ed4f7a18b20d4", 45 | "parentUid" : "b3d10c61a910c159702189dc22cdc1ff", 46 | "status" : "passed", 47 | "time" : { 48 | "start" : 1612427970157, 49 | "stop" : 1612427971195, 50 | "duration" : 1038 51 | }, 52 | "flaky" : false, 53 | "newFailed" : false, 54 | "parameters" : [ "{'summary': 'getAdultCurbactList', 'describe': 'test_getAdultCurbactList', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'getAdultCurbactList_response.json'}}" ] 55 | } ], 56 | "uid" : "b3d10c61a910c159702189dc22cdc1ff" 57 | }, { 58 | "name" : "test_initCanSelInfo", 59 | "children" : [ { 60 | "name" : "test_initCanSelInfo[case_data0]", 61 | "uid" : "aa8dfcaa510813c2", 62 | "parentUid" : "b77503932ded1905a43d0db61688ff42", 63 | "status" : "passed", 64 | "time" : { 65 | "start" : 1612427971198, 66 | "stop" : 1612427972269, 67 | "duration" : 1071 68 | }, 69 | "flaky" : false, 70 | "newFailed" : false, 71 | "parameters" : [ "{'summary': 'initCanSelInfo', 'describe': 'test_initCanSelInfo', 'parameter': 'initCanSelInfo_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'initCanSelInfo_response.json'}}" ] 72 | } ], 73 | "uid" : "b77503932ded1905a43d0db61688ff42" 74 | } ], 75 | "uid" : "PyDemo.testcase.register" 76 | } ] 77 | } -------------------------------------------------------------------------------- /PyDemo/report/html/plugins/behaviors/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | allure.api.addTranslation('en', { 4 | tab: { 5 | behaviors: { 6 | name: 'Behaviors' 7 | } 8 | }, 9 | widget: { 10 | behaviors: { 11 | name: 'Features by stories', 12 | showAll: 'show all' 13 | } 14 | } 15 | }); 16 | 17 | allure.api.addTranslation('ru', { 18 | tab: { 19 | behaviors: { 20 | name: 'Функциональность' 21 | } 22 | }, 23 | widget: { 24 | behaviors: { 25 | name: 'Функциональность', 26 | showAll: 'показать все' 27 | } 28 | } 29 | }); 30 | 31 | allure.api.addTranslation('zh', { 32 | tab: { 33 | behaviors: { 34 | name: '功能' 35 | } 36 | }, 37 | widget: { 38 | behaviors: { 39 | name: '特性场景', 40 | showAll: '显示所有' 41 | } 42 | } 43 | }); 44 | 45 | allure.api.addTranslation('de', { 46 | tab: { 47 | behaviors: { 48 | name: 'Verhalten' 49 | } 50 | }, 51 | widget: { 52 | behaviors: { 53 | name: 'Features nach Stories', 54 | showAll: 'Zeige alle' 55 | } 56 | } 57 | }); 58 | 59 | allure.api.addTranslation('he', { 60 | tab: { 61 | behaviors: { 62 | name: 'התנהגויות' 63 | } 64 | }, 65 | widget: { 66 | behaviors: { 67 | name: 'תכונות לפי סיפורי משתמש', 68 | showAll: 'הצג הכול' 69 | } 70 | } 71 | }); 72 | 73 | allure.api.addTranslation('br', { 74 | tab: { 75 | behaviors: { 76 | name: 'Comportamentos' 77 | } 78 | }, 79 | widget: { 80 | behaviors: { 81 | name: 'Funcionalidades por história', 82 | showAll: 'Mostrar tudo' 83 | } 84 | } 85 | }); 86 | 87 | allure.api.addTranslation('ja', { 88 | tab: { 89 | behaviors: { 90 | name: '振る舞い' 91 | } 92 | }, 93 | widget: { 94 | behaviors: { 95 | name: 'ストーリー別の機能', 96 | showAll: '全て表示' 97 | } 98 | } 99 | }); 100 | 101 | allure.api.addTranslation('es', { 102 | tab: { 103 | behaviors: { 104 | name: 'Funcionalidades' 105 | } 106 | }, 107 | widget: { 108 | behaviors: { 109 | name: 'Funcionalidades por Historias de Usuario', 110 | showAll: 'mostrar todo' 111 | } 112 | } 113 | }); 114 | 115 | allure.api.addTranslation('kr', { 116 | tab: { 117 | behaviors: { 118 | name: '동작' 119 | } 120 | }, 121 | widget: { 122 | behaviors: { 123 | name: '스토리별 기능', 124 | showAll: '전체 보기' 125 | } 126 | } 127 | }); 128 | 129 | allure.api.addTab('behaviors', { 130 | title: 'tab.behaviors.name', icon: 'fa fa-list', 131 | route: 'behaviors(/)(:testGroup)(/)(:testResult)(/)(:testResultTab)(/)', 132 | onEnter: (function (testGroup, testResult, testResultTab) { 133 | return new allure.components.TreeLayout({ 134 | testGroup: testGroup, 135 | testResult: testResult, 136 | testResultTab: testResultTab, 137 | tabName: 'tab.behaviors.name', 138 | baseUrl: 'behaviors', 139 | url: 'data/behaviors.json', 140 | csvUrl: 'data/behaviors.csv' 141 | }); 142 | }) 143 | }); 144 | 145 | allure.api.addWidget('widgets', 'behaviors', allure.components.WidgetStatusView.extend({ 146 | rowTag: 'a', 147 | title: 'widget.behaviors.name', 148 | baseUrl: 'behaviors', 149 | showLinks: true 150 | })); -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/1dd259f7ca780bf0.attach: -------------------------------------------------------------------------------- 1 | {'success': True, 'code': None, 'msg': '返回成功', 'data': {'totalPage': 4, 'list': [{'bactCode': None, 'bactValidate': '2022-02-02 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20220202', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-01-28 15:31:48', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'CC0EF5CA-4EC0-D100-25EB-DAD3F6E5F6E0', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-01-28 15:32:36', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 9999, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-02 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20220202', 'bizType': 1, 'coreName': '辽宁成大', 'corpSimpName': '辽宁成大', 'createDate': '2021-01-28 15:31:49', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '3E8725A8-D8FE-0F8F-0F60-0D7844F02A5F', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '冻干狂犬病疫苗Vero', 'materType': '86901202000020', 'materTypeCode': '1', 'modifyDate': '2021-01-28 15:32:40', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒4支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbym', 'qty': 9999, 'speCode': None, 'speCodeName': '0.5ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1001'}, {'bactCode': None, 'bactValidate': '2022-02-02 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20220202', 'bizType': 1, 'coreName': '武汉生物', 'corpSimpName': '武汉生物', 'createDate': '2021-01-28 15:31:50', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'D4D5743D-9FAB-5CEE-1750-4AC1D4835028', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬球蛋白', 'materType': '86901960000553', 'materTypeCode': '2', 'modifyDate': '2021-01-28 15:32:43', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒1支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqqdb', 'qty': 9999, 'speCode': None, 'speCodeName': '200IU', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1020'}, {'bactCode': None, 'bactValidate': '2022-02-02 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20220202', 'bizType': 2, 'coreName': '成都欧林', 'corpSimpName': '成都欧林', 'createDate': '2021-01-28 15:31:51', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '7EE9316A-5125-D09B-6127-C994616CA011', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '破伤风疫苗', 'materType': '86981089000016', 'materTypeCode': '1', 'modifyDate': '2021-01-28 15:31:51', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒1支', 'pageSize': None, 'pageType': None, 'price': 20, 'priceEditMode': None, 'pym': 'psfym', 'qty': 0, 'speCode': None, 'speCodeName': '0.5ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1001'}]}, 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/xml/11f08016-1abb-461e-9e6d-fe83310ea63b-attachment.attach: -------------------------------------------------------------------------------- 1 | {'success': True, 'code': None, 'msg': '返回成功', 'data': {'totalPage': 4, 'list': [{'bactCode': None, 'bactValidate': '2022-02-02 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20220202', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-01-28 15:31:48', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'CC0EF5CA-4EC0-D100-25EB-DAD3F6E5F6E0', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-01-28 15:32:36', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 9999, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-02 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20220202', 'bizType': 1, 'coreName': '辽宁成大', 'corpSimpName': '辽宁成大', 'createDate': '2021-01-28 15:31:49', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '3E8725A8-D8FE-0F8F-0F60-0D7844F02A5F', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '冻干狂犬病疫苗Vero', 'materType': '86901202000020', 'materTypeCode': '1', 'modifyDate': '2021-01-28 15:32:40', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒4支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbym', 'qty': 9999, 'speCode': None, 'speCodeName': '0.5ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1001'}, {'bactCode': None, 'bactValidate': '2022-02-02 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20220202', 'bizType': 1, 'coreName': '武汉生物', 'corpSimpName': '武汉生物', 'createDate': '2021-01-28 15:31:50', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'D4D5743D-9FAB-5CEE-1750-4AC1D4835028', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬球蛋白', 'materType': '86901960000553', 'materTypeCode': '2', 'modifyDate': '2021-01-28 15:32:43', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒1支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqqdb', 'qty': 9999, 'speCode': None, 'speCodeName': '200IU', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1020'}, {'bactCode': None, 'bactValidate': '2022-02-02 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20220202', 'bizType': 2, 'coreName': '成都欧林', 'corpSimpName': '成都欧林', 'createDate': '2021-01-28 15:31:51', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '7EE9316A-5125-D09B-6127-C994616CA011', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '破伤风疫苗', 'materType': '86981089000016', 'materTypeCode': '1', 'modifyDate': '2021-01-28 15:31:51', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒1支', 'pageSize': None, 'pageType': None, 'price': 20, 'priceEditMode': None, 'pym': 'psfym', 'qty': 0, 'speCode': None, 'speCodeName': '0.5ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1001'}]}, 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/html/plugins/screen-diff/index.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var settings = allure.getPluginSettings('screen-diff', {diffType: 'diff'}); 3 | 4 | function renderImage(src) { 5 | return '
' + 6 | '' + 7 | '
'; 8 | } 9 | 10 | function renderDiffContent(type, data) { 11 | function findImage(name) { 12 | if (data.testStage && data.testStage.attachments) { 13 | return data.testStage.attachments.filter(function (attachment) { 14 | return attachment.name === name; 15 | })[0]; 16 | } 17 | return null; 18 | } 19 | 20 | var diffImage = findImage('diff'); 21 | var actualImage = findImage('actual'); 22 | var expectedImage = findImage('expected'); 23 | 24 | if (!diffImage && !actualImage && !expectedImage) { 25 | return 'Diff, actual and expected image have not been provided.'; 26 | } 27 | 28 | if (type === 'diff') { 29 | if (!diffImage) { 30 | return renderImage(actualImage.source); 31 | } 32 | return renderImage(diffImage.source); 33 | } 34 | if (type === 'overlay') { 35 | return '
' + 36 | '' + 37 | '
' + 38 | '' + 39 | '
' + 40 | '
'; 41 | } 42 | } 43 | 44 | var ScreenDiffView = Backbone.Marionette.View.extend({ 45 | className: 'pane__section', 46 | events: { 47 | 'click [name="screen-diff-type"]': 'onDiffTypeChange', 48 | 'mousemove .screen-diff__overlay': 'onOverlayMove' 49 | }, 50 | templateContext: function () { 51 | return { 52 | diffType: settings.get('diffType') 53 | } 54 | }, 55 | template: function (data) { 56 | var testType = data.labels.filter(function (label) { 57 | return label.name === 'testType' 58 | })[0]; 59 | 60 | if (!testType || testType.value !== 'screenshotDiff') { 61 | return ''; 62 | } 63 | 64 | return '

Screen Diff

' + 65 | '
' + 66 | '
' + 67 | '' + 68 | '' + 69 | '
' + 70 | renderDiffContent(data.diffType, data) + 71 | '
'; 72 | }, 73 | adjustImageSize: function (event) { 74 | var overImage = this.$(event.target); 75 | overImage.width(overImage.width()); 76 | }, 77 | onRender: function () { 78 | const diffType = settings.get('diffType'); 79 | this.$('[name="screen-diff-type"][value="' + diffType + '"]').prop('checked', true); 80 | if (diffType === 'overlay') { 81 | this.$('.screen-diff__image-over img').on('load', this.adjustImageSize.bind(this)); 82 | } 83 | }, 84 | onOverlayMove: function (event) { 85 | var pageX = event.pageX; 86 | var containerScroll = this.$('.screen-diff__container').scrollLeft(); 87 | var elementX = event.currentTarget.getBoundingClientRect().left; 88 | var delta = pageX - elementX + containerScroll; 89 | this.$('.screen-diff__image-over').width(delta); 90 | }, 91 | onDiffTypeChange: function (event) { 92 | settings.save('diffType', event.target.value); 93 | this.render(); 94 | } 95 | }); 96 | allure.api.addTestResultBlock(ScreenDiffView, {position: 'before'}); 97 | })(); 98 | -------------------------------------------------------------------------------- /PyDemo/report/html/data/suites.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid" : "98d3104e051c652961429bf95fa0b5d6", 3 | "name" : "suites", 4 | "children" : [ { 5 | "name" : "PyDemo.testcase.register", 6 | "children" : [ { 7 | "name" : "test_addOrUpCurBact", 8 | "children" : [ { 9 | "name" : "TestRegister", 10 | "children" : [ { 11 | "name" : "test_addOrUpCurBact[case_data0]", 12 | "uid" : "e5c5230705b9bfbb", 13 | "parentUid" : "96cf3c8a2ca39e22e5b7f098e19443e6", 14 | "status" : "broken", 15 | "time" : { 16 | "start" : 1612427966998, 17 | "stop" : 1612427969076, 18 | "duration" : 2078 19 | }, 20 | "flaky" : false, 21 | "newFailed" : false, 22 | "parameters" : [ "{'summary': 'addOrUpCurBact', 'describe': 'test_addOrUpCurBact', 'parameter': 'addOrUpCurBact_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': None, 'callTime': None}}}" ] 23 | } ], 24 | "uid" : "96cf3c8a2ca39e22e5b7f098e19443e6" 25 | } ], 26 | "uid" : "30d905cbf9519c502aab8f10d2f6663f" 27 | }, { 28 | "name" : "test_findParam", 29 | "children" : [ { 30 | "name" : "TestRegister", 31 | "children" : [ { 32 | "name" : "test_findParam[case_data0]", 33 | "uid" : "10d4bd6301177f6", 34 | "parentUid" : "3e11f0c9e3a57152e27e3c6d7c2d9a03", 35 | "status" : "passed", 36 | "time" : { 37 | "start" : 1612427969141, 38 | "stop" : 1612427970154, 39 | "duration" : 1013 40 | }, 41 | "flaky" : false, 42 | "newFailed" : false, 43 | "parameters" : [ "{'summary': 'findParam', 'describe': 'test_findParam', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}}}" ] 44 | } ], 45 | "uid" : "3e11f0c9e3a57152e27e3c6d7c2d9a03" 46 | } ], 47 | "uid" : "4ba21b42dff4a05b71ecb42a7c5fada5" 48 | }, { 49 | "name" : "test_getAdultCurbactList", 50 | "children" : [ { 51 | "name" : "TestRegister", 52 | "children" : [ { 53 | "name" : "test_getAdultCurbactList[case_data0]", 54 | "uid" : "7d4ed4f7a18b20d4", 55 | "parentUid" : "993ed7e734c76ba1ee0cb4ddf1948c32", 56 | "status" : "passed", 57 | "time" : { 58 | "start" : 1612427970157, 59 | "stop" : 1612427971195, 60 | "duration" : 1038 61 | }, 62 | "flaky" : false, 63 | "newFailed" : false, 64 | "parameters" : [ "{'summary': 'getAdultCurbactList', 'describe': 'test_getAdultCurbactList', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'getAdultCurbactList_response.json'}}" ] 65 | } ], 66 | "uid" : "993ed7e734c76ba1ee0cb4ddf1948c32" 67 | } ], 68 | "uid" : "dcc4595687c7e6954f35d1fbad0beeea" 69 | }, { 70 | "name" : "test_initCanSelInfo", 71 | "children" : [ { 72 | "name" : "TestRegister", 73 | "children" : [ { 74 | "name" : "test_initCanSelInfo[case_data0]", 75 | "uid" : "aa8dfcaa510813c2", 76 | "parentUid" : "322bc911d056a6689fb9c025a5b284a3", 77 | "status" : "passed", 78 | "time" : { 79 | "start" : 1612427971198, 80 | "stop" : 1612427972269, 81 | "duration" : 1071 82 | }, 83 | "flaky" : false, 84 | "newFailed" : false, 85 | "parameters" : [ "{'summary': 'initCanSelInfo', 'describe': 'test_initCanSelInfo', 'parameter': 'initCanSelInfo_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'initCanSelInfo_response.json'}}" ] 86 | } ], 87 | "uid" : "322bc911d056a6689fb9c025a5b284a3" 88 | } ], 89 | "uid" : "6baf0d71cf820ff083fdfcd7ca841456" 90 | } ], 91 | "uid" : "2ee94b824b159deda8131714c488ddf3" 92 | } ] 93 | } -------------------------------------------------------------------------------- /PyDemo/page/perRelated/addAudltCard_response.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "summary": "addAudltCard", 4 | "body": { 5 | "callTime": "2021-03-12 10:05:01", 6 | "code": null, 7 | "data": { 8 | "adultInforms": [], 9 | "adultInquireBean": null, 10 | "inocStationList": [], 11 | "refuseinocList": [], 12 | "tdAdult": { 13 | "accountName": "本县", 14 | "adultAccountCode": 1002, 15 | "adultAccountStr": null, 16 | "adultAddressdistrict": "AUTO99", 17 | "adultAddressregion": "3202000000", 18 | "adultAparetel": null, 19 | "adultApptime": null, 20 | "adultArtimove": 0, 21 | "adultBirthday": "2015-03-03 00:00:00", 22 | "adultBirthdaystr": null, 23 | "adultCode": "3202112002815000002", 24 | "adultCodeStr": null, 25 | "adultCountryCode": "156", 26 | "adultCreatedate": "2021-03-12 10:05:01", 27 | "adultCreateman": "3202112002008", 28 | "adultCreatemanName": "马山山", 29 | "adultCreatemanNo": null, 30 | "adultCreatesite": "3202112002", 31 | "adultCreatesiteName": "马山社区", 32 | "adultCurdepartment": "3202112002", 33 | "adultCurdepartmentName": "马山社区", 34 | "adultDeaddate": null, 35 | "adultDelmark": 0, 36 | "adultDeltime": null, 37 | "adultEduCode": null, 38 | "adultEwmCard": null, 39 | "adultFatherno": null, 40 | "adultFathernoType": null, 41 | "adultGuard": null, 42 | "adultHabiCode": "32021100", 43 | "adultHabiStr": null, 44 | "adultHabiaddress": "AUTO99", 45 | "adultHereCode": 1001, 46 | "adultHereStr": null, 47 | "adultIfapp": 0, 48 | "adultIfdead": 0, 49 | "adultIfwxin": 0, 50 | "adultJkdaCode": null, 51 | "adultJobCode": null, 52 | "adultLeavedate": "2021-03-12 10:05:01", 53 | "adultLock": 0, 54 | "adultMarry": null, 55 | "adultMobile": "19999999999", 56 | "adultMotherno": null, 57 | "adultMothernoType": null, 58 | "adultName": "AUTO99", 59 | "adultNationCode": "1001", 60 | "adultNo": "9999999999999", 61 | "adultNoType": "2", 62 | "adultRelCode": null, 63 | "adultRemark": null, 64 | "adultResiCode": 1, 65 | "adultResiStr": null, 66 | "adultSchCode": null, 67 | "adultSchName": null, 68 | "adultSex": "1", 69 | "adultTypeCode": null, 70 | "adultWxintime": null, 71 | "age": 6, 72 | "createDate": "2021-03-12 10:05:01", 73 | "createManCode": "3202112002008", 74 | "empCode": null, 75 | "habiName": "滨湖区", 76 | "hasRefInoc": 0, 77 | "hereName": "在册", 78 | "ifInform": null, 79 | "ifInquire": null, 80 | "isqr": 0, 81 | "modifyDate": "2021-03-12 10:05:01", 82 | "modifyManCode": "3202112002008", 83 | "modifyUnitCode": "3202112002", 84 | "moveDate": null, 85 | "photoUrl": null, 86 | "resiName": "常住", 87 | "showPhotoUrl": null, 88 | "sysEditDate": null, 89 | "type": null, 90 | "unitCode": null, 91 | "unitSimpname": null 92 | }, 93 | "tdAdultInoculation": [], 94 | "varIndex": [] 95 | }, 96 | "msg": "返回成功", 97 | "success": true 98 | } 99 | } 100 | ] -------------------------------------------------------------------------------- /PyDemo/report/xml/dfe15ef8-3724-4710-b687-fd5f753f0ef0-result.json: -------------------------------------------------------------------------------- 1 | {"name": "test_addOrUpCurBact[case_data0]", "status": "broken", "statusDetails": {"message": "Exception: JSON格式校验,关键字 success 返回结果 True 与期望结果 None 类型不符", "trace": "self = \ncase_data = {'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'callTime': None, 'code': None, 'data...tCode': '280101', 'bactValidate': '2022-02-04', 'batnmb': '20110101', 'bizType': 1, ...}}, 'summary': 'addOrUpCurBact'}\n\n @pytest.mark.parametrize(\"case_data\", case_dict[\"test_case\"])\n @allure.story(\"test_addOrUpCurBact\")\n def test_addOrUpCurBact(self, case_data):\n # 初始化请求:执行前置接口+替换关联变量\n test_info, case_data = init_premise(case_dict[\"test_info\"], case_data, case_path)\n # 发送当前接口\n code, data = send_request(test_info, case_data)\n # 校验接口返回\n> check_result(case_data, code, data)\n\nPyDemo\\testcase\\register\\test_addOrUpCurBact.py:29: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\ncomm\\unit\\checkResult.py:72: in check_result\n check_json(expected_result, data)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nsrc_data = {'callTime': None, 'code': None, 'data': None, 'msg': '返回成功', ...}\ndst_data = {'callTime': None, 'code': 1, 'data': None, 'msg': '已有该批次的疫苗,请直接修改库存!', ...}\n\n def check_json(src_data, dst_data):\n \"\"\"\n 校验的json\n :param src_data: 检验内容\n :param dst_data: 接口返回的数据\n :return:\n \"\"\"\n if isinstance(src_data, dict):\n for key in src_data:\n if key not in dst_data:\n raise Exception(\"JSON格式校验,关键字 %s 不在返回结果 %s 中!\" % (key, dst_data))\n else:\n this_key = key\n if isinstance(src_data[this_key], dict) and isinstance(dst_data[this_key], dict):\n check_json(src_data[this_key], dst_data[this_key])\n elif not isinstance(src_data[this_key], type(dst_data[this_key])):\n raise Exception(\"JSON格式校验,关键字 %s 返回结果 %s 与期望结果 %s 类型不符\"\n> % (this_key, src_data[this_key], dst_data[this_key]))\nE Exception: JSON格式校验,关键字 success 返回结果 True 与期望结果 None 类型不符\n\ncomm\\unit\\checkResult.py:28: Exception"}, "steps": [{"name": "POST请求接口", "status": "passed", "attachments": [{"name": "请求接口", "source": "da39ce35-693c-4f48-92cd-7795dd783e88-attachment.attach"}, {"name": "请求地址", "source": "e9a38fd0-5f1b-4739-a472-7606737e0911-attachment.attach"}, {"name": "请求头", "source": "d3f438ee-fde7-483c-9a1b-87ce48d23359-attachment.attach"}, {"name": "请求参数", "source": "31d021db-66cf-4b6c-ae71-15a2e9953294-attachment.attach"}], "start": 1612427967004, "stop": 1612427967006}, {"name": "POST请求接口", "status": "passed", "attachments": [{"name": "请求接口", "source": "8a751566-67d8-4a28-943a-a0c8cecc3a9f-attachment.attach"}, {"name": "请求地址", "source": "a6f8bf5f-a42a-4c47-a026-243375a5685d-attachment.attach"}, {"name": "请求头", "source": "f8618d25-7423-4d9f-a777-b1bc37ee3fd5-attachment.attach"}, {"name": "请求参数", "source": "c56c0537-21bd-4b7d-b0d8-6235c48804d2-attachment.attach"}], "start": 1612427968055, "stop": 1612427968057}, {"name": "JSON格式校验结果", "status": "passed", "attachments": [{"name": "实际code", "source": "15a5ed09-71be-4302-8da3-f1a3833890c3-attachment.attach"}, {"name": "期望code", "source": "eb8ba490-0f39-42ba-9a1c-44e5ee2a0636-attachment.attach"}, {"name": "实际data", "source": "aa05cb30-25c4-4485-b7f9-1aa4fd98e692-attachment.attach"}, {"name": "期望data", "source": "5f34e443-5ec3-41cf-9002-dd92ec056d54-attachment.attach"}], "start": 1612427969074, "stop": 1612427969075}], "attachments": [{"name": "log", "source": "b996b821-aa01-4bf4-a300-a3426ab66574-attachment.txt", "type": "text/plain"}], "parameters": [{"name": "case_data", "value": "{'summary': 'addOrUpCurBact', 'describe': 'test_addOrUpCurBact', 'parameter': 'addOrUpCurBact_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': None, 'callTime': None}}}"}], "start": 1612427966998, "stop": 1612427969076, "uuid": "7632a432-2edf-4bed-9879-5a6e506f0688", "historyId": "fb868315583aa11e2cd2b0339b92f05a", "testCaseId": "c47b844e0cc323f4955b7105ea349bb7", "fullName": "PyDemo.testcase.register.test_addOrUpCurBact.TestRegister#test_addOrUpCurBact", "labels": [{"name": "story", "value": "test_addOrUpCurBact"}, {"name": "feature", "value": "register"}, {"name": "parentSuite", "value": "PyDemo.testcase.register"}, {"name": "suite", "value": "test_addOrUpCurBact"}, {"name": "subSuite", "value": "TestRegister"}, {"name": "host", "value": "Leo-PC"}, {"name": "thread", "value": "1096-MainThread"}, {"name": "framework", "value": "pytest"}, {"name": "language", "value": "cpython3"}, {"name": "package", "value": "PyDemo.testcase.register.test_addOrUpCurBact"}]} -------------------------------------------------------------------------------- /PyDemo/data/addAudltCard.chlsj: -------------------------------------------------------------------------------- 1 | [{"status":"COMPLETE","method":"POST","protocolVersion":"HTTP/1.1","scheme":"http","host":"127.0.0.1","port":30131,"actualPort":30131,"path":"/api/perRelated/addAudltCard","query":null,"tunnel":false,"keptAlive":true,"webSocket":false,"remoteAddress":"127.0.0.1/127.0.0.1","clientAddress":"/127.0.0.1","clientPort":58438,"times":{"start":"2021-03-12T10:07:03.305+08:00","requestBegin":"2021-03-12T10:07:03.305+08:00","requestComplete":"2021-03-12T10:07:03.305+08:00","responseBegin":"2021-03-12T10:07:03.497+08:00","end":"2021-03-12T10:07:03.497+08:00"},"durations":{"total":192,"dns":null,"connect":null,"ssl":null,"request":0,"response":0,"latency":192},"speeds":{"overall":"12427","request":"0","response":"0"},"totalSize":"2386","request":{"sizes":{"headers":486,"body":634},"mimeType":"application/x-www-form-urlencoded","charset":"UTF-8","contentEncoding":null,"header":{"firstLine":"POST /api/perRelated/addAudltCard HTTP/1.1","headers":[{"name":"Host","value":"127.0.0.1:30131"},{"name":"Content-Length","value":"634"},{"name":"Accept","value":"application/json, text/plain, */*"},{"name":"User-Agent","value":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"},{"name":"Content-Type","value":"application/x-www-form-urlencoded;charset=UTF-8"},{"name":"Origin","value":"http://127.0.0.1:6006"},{"name":"Referer","value":"http://127.0.0.1:6006/"},{"name":"Accept-Encoding","value":"gzip, deflate"},{"name":"Accept-Language","value":"zh-CN,zh;q=0.9"},{"name":"Connection","value":"keep-alive"}]},"body":{"text":"{\"params\":{\"adultAddressregion\":\"3202000000\",\"adultAddressdistrict\":\"测试\",\"adultCountryCode\":\"156\",\"adultNationCode\":\"1001\",\"adultNoType\":\"2\",\"adultHabiCode\":\"32021100\",\"unitCode\":\"3202112002\",\"adultAccountCode\":1002,\"adultResiCode\":1,\"adultNo\":\"9999999999999\",\"adultName\":\"测试\",\"adultSex\":\"1\",\"adultBirthday\":\"2015-03-03\",\"adultMobile\":\"19999999999\",\"adultHabiaddress\":\"测试\",\"adultArtimove\":0,\"adultIfdead\":0,\"adultHereCode\":1001,\"adultCreatesite\":\"3202112002\",\"adultCreatemanName\":\"马山山\",\"adultCreateman\":\"3202112002008\",\"adultCreatesiteName\":\"马山社区\"},\"headtoken\":\"ci3fxE80WQ7XyurO4/IKRcHql4tf3Xw/fu+VnRGKtCw=\"}","charset":"UTF-8"}},"response":{"status":200,"sizes":{"headers":427,"body":839},"mimeType":"text/plain","charset":"UTF-8","contentEncoding":"gzip","header":{"firstLine":"HTTP/1.1 200 OK","headers":[{"name":"Server","value":"nginx"},{"name":"Date","value":"Fri, 12 Mar 2021 01:59:45 GMT"},{"name":"Content-Type","value":"text/plain; charset=UTF-8"},{"name":"Transfer-Encoding","value":"chunked"},{"name":"access-control-allow-origin","value":"*"},{"name":"access-control-allow-headers","value":"Origin, X-Requested-With, Content-Type, Accept,Access-Control-Allow-Origin"},{"name":"access-control-allow-methods","value":"GET, POST,OPTIONS"},{"name":"Content-Encoding","value":"gzip"},{"name":"Proxy-Connection","value":"keep-alive"}]},"body":{"text":"{\"callTime\":\"2021-03-12 10:05:01\",\"code\":null,\"data\":{\"adultInforms\":[],\"adultInquireBean\":null,\"inocStationList\":[],\"refuseinocList\":[],\"tdAdult\":{\"accountName\":\"本县\",\"adultAccountCode\":1002,\"adultAccountStr\":null,\"adultAddressdistrict\":\"测试\",\"adultAddressregion\":\"3202000000\",\"adultAparetel\":null,\"adultApptime\":null,\"adultArtimove\":0,\"adultBirthday\":\"2015-03-03 00:00:00\",\"adultBirthdaystr\":null,\"adultCode\":\"3202112002815000002\",\"adultCodeStr\":null,\"adultCountryCode\":\"156\",\"adultCreatedate\":\"2021-03-12 10:05:01\",\"adultCreateman\":\"3202112002008\",\"adultCreatemanName\":\"马山山\",\"adultCreatemanNo\":null,\"adultCreatesite\":\"3202112002\",\"adultCreatesiteName\":\"马山社区\",\"adultCurdepartment\":\"3202112002\",\"adultCurdepartmentName\":\"马山社区\",\"adultDeaddate\":null,\"adultDelmark\":0,\"adultDeltime\":null,\"adultEduCode\":null,\"adultEwmCard\":null,\"adultFatherno\":null,\"adultFathernoType\":null,\"adultGuard\":null,\"adultHabiCode\":\"32021100\",\"adultHabiStr\":null,\"adultHabiaddress\":\"测试\",\"adultHereCode\":1001,\"adultHereStr\":null,\"adultIfapp\":0,\"adultIfdead\":0,\"adultIfwxin\":0,\"adultJkdaCode\":null,\"adultJobCode\":null,\"adultLeavedate\":\"2021-03-12 10:05:01\",\"adultLock\":0,\"adultMarry\":null,\"adultMobile\":\"19999999999\",\"adultMotherno\":null,\"adultMothernoType\":null,\"adultName\":\"测试\",\"adultNationCode\":\"1001\",\"adultNo\":\"9999999999999\",\"adultNoType\":\"2\",\"adultRelCode\":null,\"adultRemark\":null,\"adultResiCode\":1,\"adultResiStr\":null,\"adultSchCode\":null,\"adultSchName\":null,\"adultSex\":\"1\",\"adultTypeCode\":null,\"adultWxintime\":null,\"age\":6,\"createDate\":\"2021-03-12 10:05:01\",\"createManCode\":\"3202112002008\",\"empCode\":null,\"habiName\":\"滨湖区\",\"hasRefInoc\":0,\"hereName\":\"在册\",\"ifInform\":null,\"ifInquire\":null,\"isqr\":0,\"modifyDate\":\"2021-03-12 10:05:01\",\"modifyManCode\":\"3202112002008\",\"modifyUnitCode\":\"3202112002\",\"moveDate\":null,\"photoUrl\":null,\"resiName\":\"常住\",\"showPhotoUrl\":null,\"sysEditDate\":null,\"type\":null,\"unitCode\":null,\"unitSimpname\":null},\"tdAdultInoculation\":[],\"varIndex\":[]},\"msg\":\"返回成功\",\"success\":true}","charset":"UTF-8","decoded":true}}}] -------------------------------------------------------------------------------- /PyDemo/report/html/data/test-cases/aa8dfcaa510813c2.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid" : "aa8dfcaa510813c2", 3 | "name" : "test_initCanSelInfo[case_data0]", 4 | "fullName" : "PyDemo.testcase.register.test_initCanSelInfo.TestRegister#test_initCanSelInfo", 5 | "historyId" : "1155f03dcf38b2069e797022e1f66d78", 6 | "time" : { 7 | "start" : 1612427971198, 8 | "stop" : 1612427972269, 9 | "duration" : 1071 10 | }, 11 | "status" : "passed", 12 | "flaky" : false, 13 | "newFailed" : false, 14 | "beforeStages" : [ ], 15 | "testStage" : { 16 | "status" : "passed", 17 | "steps" : [ { 18 | "name" : "POST请求接口", 19 | "time" : { 20 | "start" : 1612427971221, 21 | "stop" : 1612427971223, 22 | "duration" : 2 23 | }, 24 | "status" : "passed", 25 | "steps" : [ ], 26 | "attachments" : [ { 27 | "uid" : "d4cfa82e3954b068", 28 | "name" : "请求接口", 29 | "source" : "d4cfa82e3954b068.attach", 30 | "type" : "text/plain", 31 | "size" : 14 32 | }, { 33 | "uid" : "ea0ced6a1ef79518", 34 | "name" : "请求地址", 35 | "source" : "ea0ced6a1ef79518.attach", 36 | "type" : "text/plain", 37 | "size" : 53 38 | }, { 39 | "uid" : "7f88a98d6e750e3c", 40 | "name" : "请求头", 41 | "source" : "7f88a98d6e750e3c.attach", 42 | "type" : "text/plain", 43 | "size" : 67 44 | }, { 45 | "uid" : "d7e1801c64f284ab", 46 | "name" : "请求参数", 47 | "source" : "d7e1801c64f284ab.attach", 48 | "type" : "text/plain", 49 | "size" : 452 50 | } ], 51 | "parameters" : [ ], 52 | "stepsCount" : 0, 53 | "hasContent" : true, 54 | "attachmentsCount" : 4, 55 | "shouldDisplayMessage" : false 56 | }, { 57 | "name" : "JSON格式校验结果", 58 | "time" : { 59 | "start" : 1612427972266, 60 | "stop" : 1612427972269, 61 | "duration" : 3 62 | }, 63 | "status" : "passed", 64 | "steps" : [ ], 65 | "attachments" : [ { 66 | "uid" : "a142325f6ec7dd97", 67 | "name" : "实际code", 68 | "source" : "a142325f6ec7dd97.attach", 69 | "type" : "text/plain", 70 | "size" : 3 71 | }, { 72 | "uid" : "d57f284c2a250050", 73 | "name" : "期望code", 74 | "source" : "d57f284c2a250050.attach", 75 | "type" : "text/plain", 76 | "size" : 3 77 | }, { 78 | "uid" : "1c85ce2c08ae706f", 79 | "name" : "实际data", 80 | "source" : "1c85ce2c08ae706f.attach", 81 | "type" : "text/plain", 82 | "size" : 49289 83 | }, { 84 | "uid" : "12f1d79c71da9096", 85 | "name" : "期望data", 86 | "source" : "12f1d79c71da9096.attach", 87 | "type" : "text/plain", 88 | "size" : 49289 89 | } ], 90 | "parameters" : [ ], 91 | "stepsCount" : 0, 92 | "hasContent" : true, 93 | "attachmentsCount" : 4, 94 | "shouldDisplayMessage" : false 95 | } ], 96 | "attachments" : [ { 97 | "uid" : "6493cdb7851bdbc9", 98 | "name" : "log", 99 | "source" : "6493cdb7851bdbc9.txt", 100 | "type" : "text/plain", 101 | "size" : 101512 102 | } ], 103 | "parameters" : [ ], 104 | "stepsCount" : 2, 105 | "hasContent" : true, 106 | "attachmentsCount" : 9, 107 | "shouldDisplayMessage" : false 108 | }, 109 | "afterStages" : [ ], 110 | "labels" : [ { 111 | "name" : "story", 112 | "value" : "test_initCanSelInfo" 113 | }, { 114 | "name" : "feature", 115 | "value" : "register" 116 | }, { 117 | "name" : "parentSuite", 118 | "value" : "PyDemo.testcase.register" 119 | }, { 120 | "name" : "suite", 121 | "value" : "test_initCanSelInfo" 122 | }, { 123 | "name" : "subSuite", 124 | "value" : "TestRegister" 125 | }, { 126 | "name" : "host", 127 | "value" : "Leo-PC" 128 | }, { 129 | "name" : "thread", 130 | "value" : "1096-MainThread" 131 | }, { 132 | "name" : "framework", 133 | "value" : "pytest" 134 | }, { 135 | "name" : "language", 136 | "value" : "cpython3" 137 | }, { 138 | "name" : "package", 139 | "value" : "PyDemo.testcase.register.test_initCanSelInfo" 140 | }, { 141 | "name" : "resultFormat", 142 | "value" : "allure2" 143 | } ], 144 | "parameters" : [ { 145 | "name" : "case_data", 146 | "value" : "{'summary': 'initCanSelInfo', 'describe': 'test_initCanSelInfo', 'parameter': 'initCanSelInfo_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'initCanSelInfo_response.json'}}" 147 | } ], 148 | "links" : [ ], 149 | "hidden" : false, 150 | "retry" : false, 151 | "extra" : { 152 | "severity" : "normal", 153 | "retries" : [ ], 154 | "categories" : [ ], 155 | "tags" : [ ] 156 | }, 157 | "source" : "aa8dfcaa510813c2.json", 158 | "parameterValues" : [ "{'summary': 'initCanSelInfo', 'describe': 'test_initCanSelInfo', 'parameter': 'initCanSelInfo_request.json', 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'initCanSelInfo_response.json'}}" ] 159 | } -------------------------------------------------------------------------------- /comm/utils/randomly.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2020/12/10 3 | # @Author : Leo Zhang 4 | # @File : randomly.py 5 | # ************************* 6 | import string 7 | import random 8 | import datetime 9 | from dateutil.relativedelta import relativedelta 10 | 11 | 12 | def random_str(str_len): 13 | """从a-zA-Z0-9生成制定数量的随机字符 14 | 15 | :param str_len: 字符串长度 16 | :return: 17 | """ 18 | try: 19 | str_len = int(str_len) 20 | except ValueError: 21 | raise Exception("调用随机字符失败,[ %s ]长度参数有误!" % str_len) 22 | strings = ''.join(random.sample(string.hexdigits, +str_len)) 23 | return strings 24 | 25 | 26 | def random_int(scope): 27 | """获取随机整型数据 28 | 29 | :param scope: 数据范围 30 | :return: 31 | """ 32 | try: 33 | start_num, end_num = scope.split(",") 34 | start_num = int(start_num) 35 | end_num = int(end_num) 36 | except ValueError: 37 | raise Exception("调用随机整数失败,[ %s ]范围参数有误!" % str(scope)) 38 | if start_num <= end_num: 39 | number = random.randint(start_num, end_num) 40 | else: 41 | number = random.randint(end_num, start_num) 42 | return number 43 | 44 | 45 | def random_float(data): 46 | """获取随机浮点数据 47 | 48 | :param data: 数组 49 | :return: 50 | """ 51 | try: 52 | start_num, end_num, accuracy = data.split(",") 53 | start_num = int(start_num) 54 | end_num = int(end_num) 55 | accuracy = int(accuracy) 56 | except ValueError: 57 | raise Exception("调用随机浮点数失败,[ %s ]范围参数或精度有误!" % data) 58 | 59 | if start_num <= end_num: 60 | number = random.uniform(start_num, end_num) 61 | else: 62 | number = random.uniform(end_num, start_num) 63 | number = round(number, accuracy) 64 | return number 65 | 66 | 67 | def random_choice(data): 68 | """获取数组随机值 69 | 70 | :param data: 数组 71 | :return: 72 | """ 73 | _list = data.split(",") 74 | each = random.choice(_list) 75 | return each 76 | 77 | 78 | def get_date_mark(now, mark, num): 79 | if 'y' == mark: 80 | return now + relativedelta(years=num) 81 | elif 'm' == mark: 82 | return now + relativedelta(months=num) 83 | elif 'd' == mark: 84 | return now + relativedelta(days=num) 85 | elif 'h' == mark: 86 | return now + relativedelta(hours=num) 87 | elif 'M' == mark: 88 | return now + relativedelta(minutes=num) 89 | elif 's' == mark: 90 | return now + relativedelta(seconds=num) 91 | else: 92 | raise Exception("日期字段标识[ %s ]错误, 请使用[年y,月m,日d,时h,分M,秒s]标识!" % mark) 93 | 94 | 95 | def generate_date(expr=''): 96 | """生成日期对象(不含时分秒) 97 | 98 | :param expr: 日期表达式,如"d-1"代表日期减1 99 | :return: 100 | """ 101 | today = datetime.date.today() 102 | if expr: 103 | try: 104 | mark = expr[:1] 105 | num = int(expr[1:]) 106 | except (TypeError, NameError): 107 | raise Exception("调用生成日期失败,日期表达式[ %s ]有误!" % expr) 108 | return get_date_mark(today, mark, num) 109 | else: 110 | return today 111 | 112 | 113 | def generate_datetime(expr=''): 114 | """生成日期时间对象(含时分秒) 115 | 116 | :param expr: 日期表达式,如"d-1"代表日期减1 117 | :return: 118 | """ 119 | now = datetime.datetime.now().replace(microsecond=0) 120 | if expr: 121 | try: 122 | mark = expr[:1] 123 | num = int(expr[1:]) 124 | except (TypeError, NameError): 125 | raise Exception("调用生成日期失败,日期表达式[ %s ]有误!" % expr) 126 | return get_date_mark(now, mark, num) 127 | else: 128 | return now 129 | 130 | 131 | def generate_timestamp(expr=''): 132 | """生成时间戳(13位) 133 | 134 | :param expr: 日期表达式,如"d-1"代表日期减1 135 | :return: 136 | """ 137 | datetime_obj = generate_datetime(expr) 138 | return int(datetime.datetime.timestamp(datetime_obj)) * 1000 139 | 140 | 141 | def generate_guid(): 142 | """基于MAC地址+时间戳+随机数来生成GUID 143 | 144 | :param: 145 | :return: 146 | """ 147 | import uuid 148 | return str(uuid.uuid1()).upper() 149 | 150 | 151 | def generate_wxid(): 152 | """基于AUTO标识+26位英文字母大小写+数字生成伪微信ID 153 | 154 | :param: 155 | :return: 156 | """ 157 | return 'AUTO' + ''.join(random.sample(string.ascii_letters + string.digits, 24)) 158 | 159 | 160 | def generate_noid(expr=''): 161 | """基于6位随机数字+出生日期+4位随机数生成伪身份证 162 | 163 | :param expr: 日期表达式,如"d-1"代表日期减1 164 | :return: 165 | """ 166 | birthday = generate_date(expr) 167 | birthday = str(birthday).replace('-', '') 168 | return int(str(random.randint(100000, 999999)) + birthday + str(random.randint(1000, 9999))) 169 | 170 | 171 | def generate_phone(): 172 | """基于三大运营商号段+随机数生成伪手机号 173 | 174 | :param: 175 | :return: 176 | """ 177 | ctcc = [133,153,173,177,180,181,189,191,193,199] 178 | cucc = [130,131,132,155,156,166,175,176,185,186,166] 179 | cmcc = [134,135,136,137,138,139,147,150,151,152,157,158,159,172,178,182,183,184,187,188,198] 180 | begin = 10 ** 7 181 | end = 10 ** 8 - 1 182 | prefix = random.choice(ctcc+cucc+cmcc) 183 | return str(prefix) + str(random.randint(begin, end)) 184 | 185 | 186 | if __name__ == '__main__': 187 | # 简单随机数据 188 | print(random_str(16)) 189 | print(random_int("100,200")) 190 | print(random_float("200,100,5")) 191 | print(random_choice("aaa,bbb,ccc")) 192 | 193 | # 生成日期数据 194 | print(generate_date()) 195 | print(generate_datetime()) 196 | print(generate_date('m+1')) 197 | print(generate_datetime('d+1')) 198 | print(generate_timestamp('s+100')) 199 | print(generate_noid('y-18')) 200 | 201 | # 生成常用数据 202 | print(generate_guid()) 203 | print(generate_wxid()) 204 | print(generate_noid()) 205 | print(generate_phone()) -------------------------------------------------------------------------------- /PyDemo/report/html/data/test-cases/10d4bd6301177f6.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid" : "10d4bd6301177f6", 3 | "name" : "test_findParam[case_data0]", 4 | "fullName" : "PyDemo.testcase.register.test_findParam.TestRegister#test_findParam", 5 | "historyId" : "62cffe5b54c1489b5c40af1b7f11c19b", 6 | "time" : { 7 | "start" : 1612427969141, 8 | "stop" : 1612427970154, 9 | "duration" : 1013 10 | }, 11 | "status" : "passed", 12 | "flaky" : false, 13 | "newFailed" : false, 14 | "beforeStages" : [ ], 15 | "testStage" : { 16 | "status" : "passed", 17 | "steps" : [ { 18 | "name" : "POST请求接口", 19 | "time" : { 20 | "start" : 1612427969143, 21 | "stop" : 1612427969144, 22 | "duration" : 1 23 | }, 24 | "status" : "passed", 25 | "steps" : [ ], 26 | "attachments" : [ { 27 | "uid" : "de7b006637c1f824", 28 | "name" : "请求接口", 29 | "source" : "de7b006637c1f824.attach", 30 | "type" : "text/plain", 31 | "size" : 9 32 | }, { 33 | "uid" : "6d6990d6bc7da779", 34 | "name" : "请求地址", 35 | "source" : "6d6990d6bc7da779.attach", 36 | "type" : "text/plain", 37 | "size" : 48 38 | }, { 39 | "uid" : "48d8349a567cd920", 40 | "name" : "请求头", 41 | "source" : "48d8349a567cd920.attach", 42 | "type" : "text/plain", 43 | "size" : 67 44 | }, { 45 | "uid" : "b2611d9bc9f7e7f2", 46 | "name" : "请求参数", 47 | "source" : "b2611d9bc9f7e7f2.attach", 48 | "type" : "text/plain", 49 | "size" : 149 50 | } ], 51 | "parameters" : [ ], 52 | "stepsCount" : 0, 53 | "hasContent" : true, 54 | "attachmentsCount" : 4, 55 | "shouldDisplayMessage" : false 56 | }, { 57 | "name" : "JSON格式校验结果", 58 | "time" : { 59 | "start" : 1612427970152, 60 | "stop" : 1612427970154, 61 | "duration" : 2 62 | }, 63 | "status" : "passed", 64 | "steps" : [ ], 65 | "attachments" : [ { 66 | "uid" : "b5dbaecb2dacdb90", 67 | "name" : "实际code", 68 | "source" : "b5dbaecb2dacdb90.attach", 69 | "type" : "text/plain", 70 | "size" : 3 71 | }, { 72 | "uid" : "a10e5441521817af", 73 | "name" : "期望code", 74 | "source" : "a10e5441521817af.attach", 75 | "type" : "text/plain", 76 | "size" : 3 77 | }, { 78 | "uid" : "5627e81e1f308560", 79 | "name" : "实际data", 80 | "source" : "5627e81e1f308560.attach", 81 | "type" : "text/plain", 82 | "size" : 92 83 | }, { 84 | "uid" : "a2493f73f5b55797", 85 | "name" : "期望data", 86 | "source" : "a2493f73f5b55797.attach", 87 | "type" : "text/plain", 88 | "size" : 92 89 | } ], 90 | "parameters" : [ ], 91 | "stepsCount" : 0, 92 | "hasContent" : true, 93 | "attachmentsCount" : 4, 94 | "shouldDisplayMessage" : false 95 | } ], 96 | "attachments" : [ { 97 | "uid" : "64a95aad22c4bff3", 98 | "name" : "log", 99 | "source" : "64a95aad22c4bff3.txt", 100 | "type" : "text/plain", 101 | "size" : 2177 102 | } ], 103 | "parameters" : [ ], 104 | "stepsCount" : 2, 105 | "hasContent" : true, 106 | "attachmentsCount" : 9, 107 | "shouldDisplayMessage" : false 108 | }, 109 | "afterStages" : [ ], 110 | "labels" : [ { 111 | "name" : "story", 112 | "value" : "test_findParam" 113 | }, { 114 | "name" : "feature", 115 | "value" : "register" 116 | }, { 117 | "name" : "parentSuite", 118 | "value" : "PyDemo.testcase.register" 119 | }, { 120 | "name" : "suite", 121 | "value" : "test_findParam" 122 | }, { 123 | "name" : "subSuite", 124 | "value" : "TestRegister" 125 | }, { 126 | "name" : "host", 127 | "value" : "Leo-PC" 128 | }, { 129 | "name" : "thread", 130 | "value" : "1096-MainThread" 131 | }, { 132 | "name" : "framework", 133 | "value" : "pytest" 134 | }, { 135 | "name" : "language", 136 | "value" : "cpython3" 137 | }, { 138 | "name" : "package", 139 | "value" : "PyDemo.testcase.register.test_findParam" 140 | }, { 141 | "name" : "resultFormat", 142 | "value" : "allure2" 143 | } ], 144 | "parameters" : [ { 145 | "name" : "case_data", 146 | "value" : "{'summary': 'findParam', 'describe': 'test_findParam', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}}}" 147 | } ], 148 | "links" : [ ], 149 | "hidden" : false, 150 | "retry" : false, 151 | "extra" : { 152 | "severity" : "normal", 153 | "retries" : [ ], 154 | "categories" : [ ], 155 | "tags" : [ ] 156 | }, 157 | "source" : "10d4bd6301177f6.json", 158 | "parameterValues" : [ "{'summary': 'findParam', 'describe': 'test_findParam', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': {'success': True, 'code': None, 'msg': '返回成功', 'data': ['1', '1'], 'callTime': None}}}" ] 159 | } -------------------------------------------------------------------------------- /PyDemo/report/html/data/test-cases/7d4ed4f7a18b20d4.json: -------------------------------------------------------------------------------- 1 | { 2 | "uid" : "7d4ed4f7a18b20d4", 3 | "name" : "test_getAdultCurbactList[case_data0]", 4 | "fullName" : "PyDemo.testcase.register.test_getAdultCurbactList.TestRegister#test_getAdultCurbactList", 5 | "historyId" : "27801e67fb61317f40b6cdc1f8d317aa", 6 | "time" : { 7 | "start" : 1612427970157, 8 | "stop" : 1612427971195, 9 | "duration" : 1038 10 | }, 11 | "status" : "passed", 12 | "flaky" : false, 13 | "newFailed" : false, 14 | "beforeStages" : [ ], 15 | "testStage" : { 16 | "status" : "passed", 17 | "steps" : [ { 18 | "name" : "POST请求接口", 19 | "time" : { 20 | "start" : 1612427970161, 21 | "stop" : 1612427970164, 22 | "duration" : 3 23 | }, 24 | "status" : "passed", 25 | "steps" : [ ], 26 | "attachments" : [ { 27 | "uid" : "aa3749b1bd00dd8e", 28 | "name" : "请求接口", 29 | "source" : "aa3749b1bd00dd8e.attach", 30 | "type" : "text/plain", 31 | "size" : 19 32 | }, { 33 | "uid" : "436a2d6b50675cb6", 34 | "name" : "请求地址", 35 | "source" : "436a2d6b50675cb6.attach", 36 | "type" : "text/plain", 37 | "size" : 58 38 | }, { 39 | "uid" : "10ea6ae95941448c", 40 | "name" : "请求头", 41 | "source" : "10ea6ae95941448c.attach", 42 | "type" : "text/plain", 43 | "size" : 67 44 | }, { 45 | "uid" : "640913aa912828ba", 46 | "name" : "请求参数", 47 | "source" : "640913aa912828ba.attach", 48 | "type" : "text/plain", 49 | "size" : 149 50 | } ], 51 | "parameters" : [ ], 52 | "stepsCount" : 0, 53 | "hasContent" : true, 54 | "attachmentsCount" : 4, 55 | "shouldDisplayMessage" : false 56 | }, { 57 | "name" : "JSON格式校验结果", 58 | "time" : { 59 | "start" : 1612427971193, 60 | "stop" : 1612427971195, 61 | "duration" : 2 62 | }, 63 | "status" : "passed", 64 | "steps" : [ ], 65 | "attachments" : [ { 66 | "uid" : "f658b4378482d4a", 67 | "name" : "实际code", 68 | "source" : "f658b4378482d4a.attach", 69 | "type" : "text/plain", 70 | "size" : 3 71 | }, { 72 | "uid" : "a404884c53f9a95e", 73 | "name" : "期望code", 74 | "source" : "a404884c53f9a95e.attach", 75 | "type" : "text/plain", 76 | "size" : 3 77 | }, { 78 | "uid" : "4874af030f961a0", 79 | "name" : "实际data", 80 | "source" : "4874af030f961a0.attach", 81 | "type" : "text/plain", 82 | "size" : 6432 83 | }, { 84 | "uid" : "1dd259f7ca780bf0", 85 | "name" : "期望data", 86 | "source" : "1dd259f7ca780bf0.attach", 87 | "type" : "text/plain", 88 | "size" : 4196 89 | } ], 90 | "parameters" : [ ], 91 | "stepsCount" : 0, 92 | "hasContent" : true, 93 | "attachmentsCount" : 4, 94 | "shouldDisplayMessage" : false 95 | } ], 96 | "attachments" : [ { 97 | "uid" : "3b002256b197c3de", 98 | "name" : "log", 99 | "source" : "3b002256b197c3de.txt", 100 | "type" : "text/plain", 101 | "size" : 12683 102 | } ], 103 | "parameters" : [ ], 104 | "stepsCount" : 2, 105 | "hasContent" : true, 106 | "attachmentsCount" : 9, 107 | "shouldDisplayMessage" : false 108 | }, 109 | "afterStages" : [ ], 110 | "labels" : [ { 111 | "name" : "story", 112 | "value" : "test_getAdultCurbactList" 113 | }, { 114 | "name" : "feature", 115 | "value" : "register" 116 | }, { 117 | "name" : "parentSuite", 118 | "value" : "PyDemo.testcase.register" 119 | }, { 120 | "name" : "suite", 121 | "value" : "test_getAdultCurbactList" 122 | }, { 123 | "name" : "subSuite", 124 | "value" : "TestRegister" 125 | }, { 126 | "name" : "host", 127 | "value" : "Leo-PC" 128 | }, { 129 | "name" : "thread", 130 | "value" : "1096-MainThread" 131 | }, { 132 | "name" : "framework", 133 | "value" : "pytest" 134 | }, { 135 | "name" : "language", 136 | "value" : "cpython3" 137 | }, { 138 | "name" : "package", 139 | "value" : "PyDemo.testcase.register.test_getAdultCurbactList" 140 | }, { 141 | "name" : "resultFormat", 142 | "value" : "allure2" 143 | } ], 144 | "parameters" : [ { 145 | "name" : "case_data", 146 | "value" : "{'summary': 'getAdultCurbactList', 'describe': 'test_getAdultCurbactList', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'getAdultCurbactList_response.json'}}" 147 | } ], 148 | "links" : [ ], 149 | "hidden" : false, 150 | "retry" : false, 151 | "extra" : { 152 | "severity" : "normal", 153 | "retries" : [ ], 154 | "categories" : [ ], 155 | "tags" : [ ] 156 | }, 157 | "source" : "7d4ed4f7a18b20d4.json", 158 | "parameterValues" : [ "{'summary': 'getAdultCurbactList', 'describe': 'test_getAdultCurbactList', 'parameter': {'params': {'unitCode': '3202112002', 'first': 0, 'pym': '', 'pageSize': 10, 'page': 0}, 'headtoken': '${headtoken}'}, 'check': {'check_type': 'check_json', 'expected_code': 200, 'expected_result': 'getAdultCurbactList_response.json'}}" ] 159 | } -------------------------------------------------------------------------------- /comm/unit/initializePremise.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/2/3 3 | # @Author : Leo Zhang 4 | # @File : initializePremise.py 5 | # ************************** 6 | import logging 7 | import time 8 | import json 9 | import os 10 | from json import JSONDecodeError 11 | from config import PAGE_DIR, PROJECT_NAME, API_CONFIG 12 | from comm.unit import apiSend, readRelevance, replaceRelevance 13 | from comm.utils import readYaml 14 | 15 | 16 | def read_json(summary, json_obj, case_path): 17 | """ 18 | 校验内容读取 19 | :param summary: 用例名称 20 | :param json_obj: json文件或数据对象 21 | :param case_path: case路径 22 | :return: 23 | """ 24 | if not json_obj: 25 | return json_obj 26 | elif isinstance(json_obj, dict): 27 | return json_obj 28 | else: 29 | try: 30 | # 读取json文件指定用例数据 31 | with open(case_path+'/'+json_obj, "r", encoding="utf-8") as js: 32 | data_list = json.load(js) 33 | for data in data_list: 34 | if data['summary'] == summary: 35 | return data['body'] 36 | except FileNotFoundError: 37 | raise Exception("用例关联文件不存在\n文件路径: %s" % json_obj) 38 | except JSONDecodeError: 39 | raise Exception("用例关联的文件有误\n文件路径: %s" % json_obj) 40 | 41 | 42 | def init_premise(test_info, case_data, case_path): 43 | """用例前提条件执行,提取关键值 44 | 45 | :param test_info: 测试信息 46 | :param case_data: 用例数据 47 | :param case_path: 用例路径 48 | :return: 49 | """ 50 | # 获取项目公共关联值 51 | aconfig = readYaml.read_yaml_data(API_CONFIG) 52 | __relevance = aconfig[PROJECT_NAME] 53 | # 处理测试信息 54 | test_info = replaceRelevance.replace(test_info, __relevance) 55 | logging.debug("测试信息处理结果:{}".format(test_info)) 56 | # 处理Cookies 57 | if test_info['cookies']: 58 | cookies = aconfig[PROJECT_NAME]['cookies'] 59 | logging.debug("请求Cookies处理结果:{}".format(cookies)) 60 | 61 | # 判断是否存在前置接口 62 | pre_case_yaml = test_info["premise"] 63 | if pre_case_yaml: 64 | # 获取前置接口用例 65 | logging.info("获取前置接口测试用例:{}".format(pre_case_yaml)) 66 | pre_case_yaml = PAGE_DIR + pre_case_yaml 67 | pre_case_path = os.path.dirname(pre_case_yaml) 68 | pre_case_dict = readYaml.read_yaml_data(pre_case_yaml) 69 | pre_test_info = pre_case_dict['test_info'] 70 | pre_case_data = pre_case_dict['test_case'][0] 71 | # 判断前置接口是否也存在前置接口 72 | if pre_test_info["premise"]: 73 | init_premise(pre_test_info, pre_case_data, pre_case_path) 74 | 75 | for i in range(3): 76 | # 处理前置接口测试信息 77 | pre_test_info = replaceRelevance.replace(pre_test_info, __relevance) 78 | logging.debug("测试信息处理结果:{}".format(pre_test_info)) 79 | # 处理前置接口Cookies 80 | if pre_test_info['cookies']: 81 | cookies = aconfig[PROJECT_NAME]['cookies'] 82 | logging.debug("请求Cookies处理结果:{}".format(cookies)) 83 | # 处理前置接口入参:获取入参-替换关联值-发送请求 84 | pre_parameter = read_json(pre_case_data['summary'], pre_case_data['parameter'], pre_case_path) 85 | pre_parameter = replaceRelevance.replace(pre_parameter, __relevance) 86 | pre_case_data['parameter'] = pre_parameter 87 | logging.debug("请求参数处理结果:{}".format(pre_parameter)) 88 | logging.info("执行前置接口测试用例:{}".format(pre_test_info)) 89 | code, data = apiSend.send_request(pre_test_info, pre_case_data) 90 | 91 | # 检查接口是否调用成功 92 | if data: 93 | # 处理当前接口入参:获取入参-获取关联值-替换关联值 94 | parameter = read_json(case_data['summary'], case_data['parameter'], case_path) 95 | __relevance = readRelevance.get_relevance(data, parameter, __relevance) 96 | parameter = replaceRelevance.replace(parameter, __relevance) 97 | case_data['parameter'] = parameter 98 | logging.debug("请求参数处理结果:{}".format(parameter)) 99 | 100 | # 获取当前接口期望结果:获取期望结果-获取关联值-替换关联值 101 | expected_rs = read_json(case_data['summary'], case_data['check_body']['expected_result'], case_path) 102 | parameter['data'] = data 103 | __relevance = readRelevance.get_relevance(parameter, expected_rs, __relevance) 104 | expected_rs = replaceRelevance.replace(expected_rs, __relevance) 105 | case_data['check_body']['expected_result'] = expected_rs 106 | logging.debug("期望返回处理结果:{}".format(case_data)) 107 | break 108 | else: 109 | time.sleep(1) 110 | logging.error("前置接口请求失败!等待1秒后重试!") 111 | else: 112 | logging.info("前置接口请求失败!尝试三次失败!") 113 | raise Exception("获取前置接口关联数据失败!") 114 | else: 115 | # 处理当前接口入参:获取入参-获取关联值-替换关联值 116 | parameter = read_json(case_data['summary'], case_data['parameter'], case_path) 117 | parameter = replaceRelevance.replace(parameter, __relevance) 118 | case_data['parameter'] = parameter 119 | logging.debug("请求参数处理结果:{}".format(parameter)) 120 | 121 | # 获取当前接口期望结果:获取期望结果-获取关联值-替换关联值 122 | expected_rs = read_json(case_data['summary'], case_data['check_body']['expected_result'], case_path) 123 | __relevance = readRelevance.get_relevance(parameter, expected_rs, __relevance) 124 | expected_rs = replaceRelevance.replace(expected_rs, __relevance) 125 | case_data['check_body']['expected_result'] = expected_rs 126 | logging.debug("期望返回处理结果:{}".format(case_data)) 127 | 128 | return test_info, case_data 129 | -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/4874af030f961a0.attach: -------------------------------------------------------------------------------- 1 | {'success': True, 'code': None, 'msg': '返回成功', 'data': {'totalPage': 6, 'list': [{'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '$RanStr(10)', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:18:01', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'AFC56C4E-4DED-6281-2CFC-E52F5ADA80BF', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:18:01', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': 'aEc7d4F5B2', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:24:08', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '2D643A03-5201-CCF7-4589-AFEC7CCA1DC6', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:24:08', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '2F7EB0ec6D', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:23:47', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'B8827B29-164E-1ADC-549A-FE256BD47389', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:23:47', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-01-01 23:59:59', 'bacttypeGroupcode': None, 'batnmb': '20191118lkl-50', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:16:08', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 1, 'delTime': None, 'first': None, 'guid': '4AAFDB6F-C0C1-269C-91D4-BC0730EFCC30', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:16:11', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 100, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 87, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': 'B827FAC9-6291-337C-D692-885013A1FE44', 'storageGuid': 'FA9C4671-A7E3-0170-23CB-5EC7ED33F019', 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '78C53aDf02', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:20:44', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '06726F20-49FF-E3D8-6769-8B808E881E85', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:20:44', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20110101', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:25:12', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'EC6F0A3F-DCB4-C2AA-AC3C-447EEA829CA1', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:25:12', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}]}, 'callTime': None} -------------------------------------------------------------------------------- /PyDemo/report/xml/a8105e8d-2465-4d01-9dca-cec2937a0cfd-attachment.attach: -------------------------------------------------------------------------------- 1 | {'success': True, 'code': None, 'msg': '返回成功', 'data': {'totalPage': 6, 'list': [{'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '$RanStr(10)', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:18:01', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'AFC56C4E-4DED-6281-2CFC-E52F5ADA80BF', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:18:01', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': 'aEc7d4F5B2', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:24:08', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '2D643A03-5201-CCF7-4589-AFEC7CCA1DC6', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:24:08', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '2F7EB0ec6D', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:23:47', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'B8827B29-164E-1ADC-549A-FE256BD47389', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:23:47', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-01-01 23:59:59', 'bacttypeGroupcode': None, 'batnmb': '20191118lkl-50', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:16:08', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 1, 'delTime': None, 'first': None, 'guid': '4AAFDB6F-C0C1-269C-91D4-BC0730EFCC30', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:16:11', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 100, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 87, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': 'B827FAC9-6291-337C-D692-885013A1FE44', 'storageGuid': 'FA9C4671-A7E3-0170-23CB-5EC7ED33F019', 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '78C53aDf02', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:20:44', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '06726F20-49FF-E3D8-6769-8B808E881E85', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:20:44', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20110101', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:25:12', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'EC6F0A3F-DCB4-C2AA-AC3C-447EEA829CA1', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:25:12', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}]}, 'callTime': None} -------------------------------------------------------------------------------- /comm/unit/apiSend.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2021/2/2 3 | # @Author : Leo Zhang 4 | # @File : apiSend.py 5 | # *********************** 6 | import logging 7 | import allure 8 | import time 9 | from config import INTERVAL 10 | from comm.unit import apiMethod 11 | 12 | 13 | def send_request(test_info, case_data): 14 | """ 15 | 封装请求 16 | :param test_info: 测试信息 17 | :param case_data: 用例数据 18 | :return: 19 | """ 20 | try: 21 | # 获取用例基本信息 22 | host = test_info["host"] 23 | scheme = test_info["scheme"] 24 | method = test_info["method"].upper() 25 | address = test_info["address"] 26 | mime_type = test_info["mime_type"] 27 | headers = test_info["headers"] 28 | cookies = test_info["cookies"] 29 | file = test_info["file"] 30 | timeout = test_info["timeout"] 31 | summary = case_data["summary"] 32 | parameter = case_data["parameter"] 33 | except Exception as e: 34 | raise KeyError('获取用例基本信息失败:{}'.format(e)) 35 | 36 | request_url = scheme + "://" + host + address 37 | logging.info("=" * 150) 38 | logging.info("请求接口:%s" % str(summary)) 39 | logging.info("请求地址:%s" % request_url) 40 | logging.info("请求头: %s" % str(headers)) 41 | logging.info("请求参数: %s" % str(parameter)) 42 | 43 | # 判断是否保存cookies 44 | if summary == 'save_cookies': 45 | with allure.step("保存cookies信息"): 46 | allure.attach(name="请求接口", body=str(summary)) 47 | allure.attach(name="请求地址", body=request_url) 48 | allure.attach(name="请求头", body=str(headers)) 49 | allure.attach(name="请求参数", body=str(parameter)) 50 | apiMethod.save_cookie(headers=headers, 51 | address=request_url, 52 | mime_type=mime_type, 53 | data=parameter, 54 | cookies=cookies, 55 | timeout=timeout) 56 | # 判断接口请求类型 57 | if method == 'POST': 58 | logging.info("请求方法: POST") 59 | # 判断是否上传文件 60 | if file: 61 | with allure.step("POST上传文件"): 62 | allure.attach(name="请求接口", body=str(summary)) 63 | allure.attach(name="请求地址", body=request_url) 64 | allure.attach(name="请求头", body=str(headers)) 65 | allure.attach(name="请求参数", body=str(parameter)) 66 | result = apiMethod.post(headers=headers, 67 | address=request_url, 68 | mime_type=mime_type, 69 | files=parameter, 70 | cookies=cookies, 71 | timeout=timeout) 72 | else: 73 | with allure.step("POST请求接口"): 74 | allure.attach(name="请求接口", body=str(summary)) 75 | allure.attach(name="请求地址", body=request_url) 76 | allure.attach(name="请求头", body=str(headers)) 77 | allure.attach(name="请求参数", body=str(parameter)) 78 | result = apiMethod.post(headers=headers, 79 | address=request_url, 80 | mime_type=mime_type, 81 | data=parameter, 82 | cookies=cookies, 83 | timeout=timeout) 84 | elif method == 'GET': 85 | logging.info("请求方法: GET") 86 | with allure.step("GET请求接口"): 87 | allure.attach(name="请求接口", body=str(summary)) 88 | allure.attach(name="请求地址", body=request_url) 89 | allure.attach(name="请求头", body=str(headers)) 90 | allure.attach(name="请求参数", body=str(parameter)) 91 | result = apiMethod.get(headers=headers, 92 | address=request_url, 93 | data=parameter, 94 | cookies=cookies, 95 | timeout=timeout) 96 | elif method == 'PUT': 97 | logging.info("请求方法: PUT") 98 | # 判断是否上传文件 99 | if file: 100 | with allure.step("PUT上传文件"): 101 | allure.attach(name="请求接口", body=str(summary)) 102 | allure.attach(name="请求地址", body=request_url) 103 | allure.attach(name="请求头", body=str(headers)) 104 | allure.attach(name="请求参数", body=str(parameter)) 105 | result = apiMethod.put(headers=headers, 106 | address=request_url, 107 | mime_type=mime_type, 108 | files=parameter, 109 | cookies=cookies, 110 | timeout=timeout) 111 | else: 112 | with allure.step("PUT请求接口"): 113 | allure.attach(name="请求接口", body=str(summary)) 114 | allure.attach(name="请求地址", body=request_url) 115 | allure.attach(name="请求头", body=str(headers)) 116 | allure.attach(name="请求参数", body=str(parameter)) 117 | result = apiMethod.put(headers=headers, 118 | address=request_url, 119 | mime_type=mime_type, 120 | data=parameter, 121 | cookies=cookies, 122 | timeout=timeout) 123 | elif method == 'DELETE': 124 | logging.info("请求方法: DELETE") 125 | with allure.step("DELETE请求接口"): 126 | allure.attach(name="请求接口", body=str(summary)) 127 | allure.attach(name="请求地址", body=request_url) 128 | allure.attach(name="请求头", body=str(headers)) 129 | allure.attach(name="请求参数", body=str(parameter)) 130 | result = apiMethod.delete(headers=headers, 131 | address=request_url, 132 | data=parameter, 133 | cookies=cookies, 134 | timeout=timeout) 135 | else: 136 | result = {"code": None, "data": None} 137 | logging.info("请求接口结果:\n %s" % str(result)) 138 | time.sleep(INTERVAL) 139 | return result 140 | -------------------------------------------------------------------------------- /PyDemo/data/getAdultCurbactList.chlsj: -------------------------------------------------------------------------------- 1 | [{"status":"COMPLETE","method":"POST","protocolVersion":"HTTP/1.1","scheme":"http","host":"127.0.0.1","port":20037,"actualPort":20037,"path":"/api/register/getAdultCurbactList","query":null,"tunnel":false,"keptAlive":true,"webSocket":false,"remoteAddress":"127.0.0.1/127.0.0.1","clientAddress":"/127.0.0.1","clientPort":59258,"times":{"start":"2021-02-04T08:35:25.297+08:00","requestBegin":"2021-02-04T08:35:25.301+08:00","requestComplete":"2021-02-04T08:35:25.302+08:00","responseBegin":"2021-02-04T08:35:25.342+08:00","end":"2021-02-04T08:35:25.344+08:00"},"durations":{"total":43,"dns":null,"connect":null,"ssl":null,"request":1,"response":2,"latency":40},"speeds":{"overall":"113116","request":"627000","response":"2118500"},"totalSize":"4864","request":{"sizes":{"headers":490,"body":137},"mimeType":"application/x-www-form-urlencoded","charset":"UTF-8","contentEncoding":null,"header":{"firstLine":"POST /api/register/getAdultCurbactList HTTP/1.1","headers":[{"name":"Host","value":"127.0.0.1:20037"},{"name":"Content-Length","value":"137"},{"name":"Accept","value":"application/json, text/plain, */*"},{"name":"User-Agent","value":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"},{"name":"Content-Type","value":"application/x-www-form-urlencoded;charset=UTF-8"},{"name":"Origin","value":"http://127.0.0.1:6006"},{"name":"Referer","value":"http://127.0.0.1:6006/"},{"name":"Accept-Encoding","value":"gzip, deflate"},{"name":"Accept-Language","value":"zh-CN,zh;q=0.9"},{"name":"Connection","value":"keep-alive"}]},"body":{"text":"{\"params\":{\"unitCode\":\"3202112002\",\"first\":0,\"pym\":\"\",\"pageSize\":10,\"page\":0},\"headtoken\":\"/8QPAj9LlNJ1MaPd9ykD9cHql4tf3Xw/fu+VnRGKtCw=\"}","charset":"UTF-8"}},"response":{"status":200,"sizes":{"headers":396,"body":3841},"mimeType":"application/json","charset":"UTF-8","contentEncoding":null,"header":{"firstLine":"HTTP/1.1 200 ","headers":[{"name":"Server","value":"nginx/1.14.2"},{"name":"Date","value":"Thu, 04 Feb 2021 00:29:29 GMT"},{"name":"Content-Type","value":"application/json;charset=UTF-8"},{"name":"Content-Length","value":"3841"},{"name":"Access-Control-Allow-Headers","value":"Content-Type,x-requested-with,Authorization,Access-Control-Allow-Origin"},{"name":"Access-Control-Allow-Methods","value":"POST, GET, OPTIONS"},{"name":"Access-Control-Allow-Origin","value":"*"},{"name":"Access-Control-Max-Age","value":"360"},{"name":"Proxy-Connection","value":"keep-alive"}]},"body":{"text":"{\"success\":true,\"code\":null,\"msg\":\"返回成功\",\"data\":{\"totalPage\":4,\"list\":[{\"bactCode\":null,\"bactValidate\":\"2022-02-02 00:00:00\",\"bacttypeGroupcode\":null,\"batnmb\":\"20220202\",\"bizType\":1,\"coreName\":\"大连雅立峰\",\"corpSimpName\":\"大连雅立峰\",\"createDate\":\"2021-01-28 15:31:48\",\"createManCode\":\"3202112002008\",\"createManName\":null,\"createUnitcode\":\"3202112002\",\"dataType\":2,\"delTime\":null,\"first\":null,\"guid\":\"CC0EF5CA-4EC0-D100-25EB-DAD3F6E5F6E0\",\"ifAdd\":null,\"ifMulti\":0,\"ifUse\":1,\"inocCorpCode\":null,\"materName\":\"狂犬病疫苗(vero细胞)\",\"materType\":\"86901119000052\",\"materTypeCode\":\"1\",\"modifyDate\":\"2021-01-28 15:32:36\",\"modifyManCode\":\"3202112002008\",\"modifyManName\":null,\"modifyUnitcode\":\"3202112002\",\"modifytDate\":null,\"packageNum\":\"盒5支\",\"pageSize\":null,\"pageType\":null,\"price\":0,\"priceEditMode\":null,\"pym\":\"kqbymveroxb\",\"qty\":9999,\"speCode\":null,\"speCodeName\":\"1.0ml\",\"stopDate\":null,\"storageCode\":null,\"storageGuid\":null,\"storageName\":null,\"synDataList\":[],\"unitCode\":\"3202112002\",\"vaccSpeCode\":\"1002\"},{\"bactCode\":null,\"bactValidate\":\"2022-02-02 00:00:00\",\"bacttypeGroupcode\":null,\"batnmb\":\"20220202\",\"bizType\":1,\"coreName\":\"辽宁成大\",\"corpSimpName\":\"辽宁成大\",\"createDate\":\"2021-01-28 15:31:49\",\"createManCode\":\"3202112002008\",\"createManName\":null,\"createUnitcode\":\"3202112002\",\"dataType\":2,\"delTime\":null,\"first\":null,\"guid\":\"3E8725A8-D8FE-0F8F-0F60-0D7844F02A5F\",\"ifAdd\":null,\"ifMulti\":0,\"ifUse\":1,\"inocCorpCode\":null,\"materName\":\"冻干狂犬病疫苗Vero\",\"materType\":\"86901202000020\",\"materTypeCode\":\"1\",\"modifyDate\":\"2021-01-28 15:32:40\",\"modifyManCode\":\"3202112002008\",\"modifyManName\":null,\"modifyUnitcode\":\"3202112002\",\"modifytDate\":null,\"packageNum\":\"盒4支\",\"pageSize\":null,\"pageType\":null,\"price\":0,\"priceEditMode\":null,\"pym\":\"kqbym\",\"qty\":9999,\"speCode\":null,\"speCodeName\":\"0.5ml\",\"stopDate\":null,\"storageCode\":null,\"storageGuid\":null,\"storageName\":null,\"synDataList\":[],\"unitCode\":\"3202112002\",\"vaccSpeCode\":\"1001\"},{\"bactCode\":null,\"bactValidate\":\"2022-02-02 00:00:00\",\"bacttypeGroupcode\":null,\"batnmb\":\"20220202\",\"bizType\":1,\"coreName\":\"武汉生物\",\"corpSimpName\":\"武汉生物\",\"createDate\":\"2021-01-28 15:31:50\",\"createManCode\":\"3202112002008\",\"createManName\":null,\"createUnitcode\":\"3202112002\",\"dataType\":2,\"delTime\":null,\"first\":null,\"guid\":\"D4D5743D-9FAB-5CEE-1750-4AC1D4835028\",\"ifAdd\":null,\"ifMulti\":0,\"ifUse\":1,\"inocCorpCode\":null,\"materName\":\"狂犬球蛋白\",\"materType\":\"86901960000553\",\"materTypeCode\":\"2\",\"modifyDate\":\"2021-01-28 15:32:43\",\"modifyManCode\":\"3202112002008\",\"modifyManName\":null,\"modifyUnitcode\":\"3202112002\",\"modifytDate\":null,\"packageNum\":\"盒1支\",\"pageSize\":null,\"pageType\":null,\"price\":0,\"priceEditMode\":null,\"pym\":\"kqqdb\",\"qty\":9999,\"speCode\":null,\"speCodeName\":\"200IU\",\"stopDate\":null,\"storageCode\":null,\"storageGuid\":null,\"storageName\":null,\"synDataList\":[],\"unitCode\":\"3202112002\",\"vaccSpeCode\":\"1020\"},{\"bactCode\":null,\"bactValidate\":\"2022-02-02 00:00:00\",\"bacttypeGroupcode\":null,\"batnmb\":\"20220202\",\"bizType\":2,\"coreName\":\"成都欧林\",\"corpSimpName\":\"成都欧林\",\"createDate\":\"2021-01-28 15:31:51\",\"createManCode\":\"3202112002008\",\"createManName\":null,\"createUnitcode\":\"3202112002\",\"dataType\":2,\"delTime\":null,\"first\":null,\"guid\":\"7EE9316A-5125-D09B-6127-C994616CA011\",\"ifAdd\":null,\"ifMulti\":0,\"ifUse\":1,\"inocCorpCode\":null,\"materName\":\"破伤风疫苗\",\"materType\":\"86981089000016\",\"materTypeCode\":\"1\",\"modifyDate\":\"2021-01-28 15:31:51\",\"modifyManCode\":\"3202112002008\",\"modifyManName\":null,\"modifyUnitcode\":\"3202112002\",\"modifytDate\":null,\"packageNum\":\"盒1支\",\"pageSize\":null,\"pageType\":null,\"price\":20,\"priceEditMode\":null,\"pym\":\"psfym\",\"qty\":0,\"speCode\":null,\"speCodeName\":\"0.5ml\",\"stopDate\":null,\"storageCode\":null,\"storageGuid\":null,\"storageName\":null,\"synDataList\":[],\"unitCode\":\"3202112002\",\"vaccSpeCode\":\"1001\"}]},\"callTime\":null}","charset":"UTF-8"}}}] -------------------------------------------------------------------------------- /PyDemo/report/html/data/attachments/e100c861d9156d57.attach: -------------------------------------------------------------------------------- 1 | {'params': {'pageType': '0', 'unitCode': '3202112002', 'bactCode': '280101', 'materType': '86901119000052', 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'materName': '狂犬病疫苗(vero细胞)', 'inocCorpCode': '50', 'speCodeName': '1.0ml', 'vaccSpeCode': '1002', 'pym': 'kqbymveroxb', 'price': '0', 'batnmb': '20110101', 'qty': '100', 'ifUse': 1, 'dataType': 2, 'createDate': '', 'createManCode': '3202112002008', 'modifyDate': '', 'modifyManCode': '3202112002008', 'bactValidate': '2022-02-04', 'bizType': 1, 'materTypeCode': '1'}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg=', 'data': {'success': True, 'code': None, 'msg': '返回成功', 'data': {'totalPage': 6, 'list': [{'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '$RanStr(10)', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:18:01', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'AFC56C4E-4DED-6281-2CFC-E52F5ADA80BF', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:18:01', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': 'aEc7d4F5B2', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:24:08', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '2D643A03-5201-CCF7-4589-AFEC7CCA1DC6', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:24:08', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '2F7EB0ec6D', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:23:47', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'B8827B29-164E-1ADC-549A-FE256BD47389', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:23:47', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-01-01 23:59:59', 'bacttypeGroupcode': None, 'batnmb': '20191118lkl-50', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:16:08', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 1, 'delTime': None, 'first': None, 'guid': '4AAFDB6F-C0C1-269C-91D4-BC0730EFCC30', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:16:11', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 100, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 87, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': 'B827FAC9-6291-337C-D692-885013A1FE44', 'storageGuid': 'FA9C4671-A7E3-0170-23CB-5EC7ED33F019', 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '78C53aDf02', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:20:44', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '06726F20-49FF-E3D8-6769-8B808E881E85', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:20:44', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20110101', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:25:12', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'EC6F0A3F-DCB4-C2AA-AC3C-447EEA829CA1', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:25:12', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}]}, 'callTime': None}} -------------------------------------------------------------------------------- /PyDemo/report/xml/c56c0537-21bd-4b7d-b0d8-6235c48804d2-attachment.attach: -------------------------------------------------------------------------------- 1 | {'params': {'pageType': '0', 'unitCode': '3202112002', 'bactCode': '280101', 'materType': '86901119000052', 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'materName': '狂犬病疫苗(vero细胞)', 'inocCorpCode': '50', 'speCodeName': '1.0ml', 'vaccSpeCode': '1002', 'pym': 'kqbymveroxb', 'price': '0', 'batnmb': '20110101', 'qty': '100', 'ifUse': 1, 'dataType': 2, 'createDate': '', 'createManCode': '3202112002008', 'modifyDate': '', 'modifyManCode': '3202112002008', 'bactValidate': '2022-02-04', 'bizType': 1, 'materTypeCode': '1'}, 'headtoken': 'xu5YwIZFkVGczMn0H0rot2ps7zRIbvrTHNwMXx1sJXg=', 'data': {'success': True, 'code': None, 'msg': '返回成功', 'data': {'totalPage': 6, 'list': [{'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '$RanStr(10)', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:18:01', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'AFC56C4E-4DED-6281-2CFC-E52F5ADA80BF', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:18:01', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': 'aEc7d4F5B2', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:24:08', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '2D643A03-5201-CCF7-4589-AFEC7CCA1DC6', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:24:08', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '2F7EB0ec6D', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:23:47', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'B8827B29-164E-1ADC-549A-FE256BD47389', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:23:47', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-01-01 23:59:59', 'bacttypeGroupcode': None, 'batnmb': '20191118lkl-50', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:16:08', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 1, 'delTime': None, 'first': None, 'guid': '4AAFDB6F-C0C1-269C-91D4-BC0730EFCC30', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:16:11', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 100, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 87, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': 'B827FAC9-6291-337C-D692-885013A1FE44', 'storageGuid': 'FA9C4671-A7E3-0170-23CB-5EC7ED33F019', 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '78C53aDf02', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:20:44', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': '06726F20-49FF-E3D8-6769-8B808E881E85', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:20:44', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}, {'bactCode': None, 'bactValidate': '2022-02-04 00:00:00', 'bacttypeGroupcode': None, 'batnmb': '20110101', 'bizType': 1, 'coreName': '大连雅立峰', 'corpSimpName': '大连雅立峰', 'createDate': '2021-02-04 16:25:12', 'createManCode': '3202112002008', 'createManName': None, 'createUnitcode': '3202112002', 'dataType': 2, 'delTime': None, 'first': None, 'guid': 'EC6F0A3F-DCB4-C2AA-AC3C-447EEA829CA1', 'ifAdd': None, 'ifMulti': 0, 'ifUse': 1, 'inocCorpCode': None, 'materName': '狂犬病疫苗(vero细胞)', 'materType': '86901119000052', 'materTypeCode': '1', 'modifyDate': '2021-02-04 16:25:12', 'modifyManCode': '3202112002008', 'modifyManName': None, 'modifyUnitcode': '3202112002', 'modifytDate': None, 'packageNum': '盒5支', 'pageSize': None, 'pageType': None, 'price': 0, 'priceEditMode': None, 'pym': 'kqbymveroxb', 'qty': 100, 'speCode': None, 'speCodeName': '1.0ml', 'stopDate': None, 'storageCode': None, 'storageGuid': None, 'storageName': None, 'synDataList': [], 'unitCode': '3202112002', 'vaccSpeCode': '1002'}]}, 'callTime': None}} -------------------------------------------------------------------------------- /comm/unit/replaceRelevance.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # @Time : 2020/12/09 3 | # @Author : Leo Zhang 4 | # @File : replaceRelevance.py 5 | # **************************** 6 | import re 7 | from comm.utils.randomly import * 8 | 9 | pattern_var = r"\${(.*?)}" 10 | pattern_eval = r"\$Eval\((.*?)\)" 11 | pattern_str = r'\$RandStr\(([0-9]*?)\)' 12 | pattern_int = r'\$RandInt\(([0-9]*,[0-9]*?)\)' 13 | pattern_choice = r"\$RandChoice\((.*?)\)" 14 | pattern_float = r'\$RandFloat\(([0-9]*,[0-9]*,[0-9]*)\)' 15 | pattern_phone = r'\$GenPhone\(\)' 16 | pattern_guid = r'\$GenGuid\(\)' 17 | pattern_wxid = r'\$GenWxid\(\)' 18 | pattern_noid = r'\$GenNoid\((.*?)\)' 19 | pattern_date = r'\$GenDate\((.*?)\)' 20 | pattern_datetime = r'\$GenDatetime\((.*?)\)' 21 | 22 | 23 | def replace_pattern(pattern, value): 24 | """替换正则表达式 25 | 26 | :param pattern: 匹配字符 27 | :param value: 匹配值 28 | :return: 29 | """ 30 | patterns = pattern.split('(.*?)') 31 | return ''.join([patterns[0], value, patterns[-1]]) 32 | 33 | 34 | def replace_relevance(param, relevance=None): 35 | """替换变量关联值 36 | 37 | :param param: 参数对象 38 | :param relevance: 关联对象 39 | :return: 40 | """ 41 | result = re.findall(pattern_var, str(param)) 42 | if (not result) or (not relevance): 43 | pass 44 | else: 45 | for each in result: 46 | try: 47 | # 关联值只考虑一个值 48 | # value = relevance[each] 49 | # pattern = re.compile(r'\${' + each + '}') 50 | # try: 51 | # param = re.sub(pattern, value, param) 52 | # except TypeError: 53 | # param = value 54 | 55 | # 关联参数多值时一一对应替换 56 | # relevance_index = 0 57 | # if isinstance(relevance[each], list): 58 | # try: 59 | # param = re.sub(pattern, relevance[each][relevance_index], param, count=1) 60 | # relevance_index += 1 61 | # except IndexError: 62 | # relevance_index = 0 63 | # param = re.sub(pattern, relevance[each][relevance_index], param, count=1) 64 | # relevance_index += 1 65 | 66 | # 关联参数多值时指定索引值替换 67 | mark = re.findall(r"\[\-?[0-9]*\]", each) 68 | # 判断关联参数是否指定索引值var[n] 69 | if len(mark)==0: 70 | if isinstance(relevance[each], list): 71 | value = relevance[each][0] 72 | else: 73 | value = relevance[each] 74 | elif len(mark)==1: 75 | var = each.strip(mark[0]) 76 | n = int(mark[0].strip('[').strip(']')) 77 | value = relevance[var][n] 78 | each = each.replace('[', '\[').replace(']', '\]') 79 | else: 80 | var = each 81 | for m in mark: 82 | var = var.replace(m, '') 83 | n1 = int(mark[0].strip('[').strip(']')) 84 | n2 = int(mark[1].strip('[').strip(']')) 85 | value = relevance[var][n1][n2] 86 | each = each.replace('[', '\[').replace(']', '\]') 87 | 88 | # 生成正在表达式并替换关联参数 89 | pattern = re.compile('\${' + each + '}') 90 | try: 91 | if param.strip('${' + each + '}'): 92 | param = re.sub(pattern, str(value), param) 93 | else: 94 | param = re.sub(pattern, value, param) 95 | except TypeError: 96 | param = value 97 | except KeyError: 98 | raise KeyError('替换变量{0}失败,未发现变量对应关联值!\n关联列表:{1}'.format(param, relevance)) 99 | # pass 100 | return param 101 | 102 | 103 | def replace_eval(param): 104 | """替换eval表达式结果 105 | 106 | :param param: 参数对象 107 | :return: 108 | """ 109 | result = re.findall(pattern_eval, str(param)) 110 | if not result: 111 | pass 112 | else: 113 | for each in result: 114 | try: 115 | if 'import' in each: 116 | raise Exception('存在非法标识import') 117 | else: 118 | value = str(eval(each)) 119 | param = re.sub(pattern_eval, value, param) 120 | except KeyError as e: 121 | raise Exception('获取值[ % ]失败!\n%'.format(param, e)) 122 | except SyntaxError: 123 | pass 124 | return param 125 | 126 | 127 | def replace_random(param): 128 | """替换随机方法参数值 129 | 130 | :param param: 131 | :return: 132 | """ 133 | int_list = re.findall(pattern_int, str(param)) 134 | str_list = re.findall(pattern_str, str(param)) 135 | choice_list = re.findall(pattern_choice, str(param)) 136 | guid_list = re.findall(pattern_guid, str(param)) 137 | noid_list = re.findall(pattern_noid, str(param)) 138 | phone_list = re.findall(pattern_phone, str(param)) 139 | wxid_list = re.findall(pattern_wxid, str(param)) 140 | date_list = re.findall(pattern_date, str(param)) 141 | datetime_list = re.findall(pattern_datetime, str(param)) 142 | 143 | if len(str_list): 144 | for each in str_list: 145 | # pattern = re.compile(r'\$RandStr\(' + each + r'\)') 146 | # param = re.sub(pattern, str(random_str(each)), param, count=1) 147 | param = re.sub(pattern_str, str(random_str(each)), param, count=1) 148 | 149 | if len(int_list): 150 | for each in int_list: 151 | param = re.sub(pattern_int, str(random_int(each)), param, count=1) 152 | 153 | if len(choice_list): 154 | for each in choice_list: 155 | param = re.sub(pattern_choice, str(random_choice(each)), param, count=1) 156 | 157 | if len(date_list): 158 | for each in date_list: 159 | param = re.sub(pattern_date, str(generate_date(each)), param, count=1) 160 | 161 | if len(datetime_list): 162 | for each in datetime_list: 163 | param = re.sub(pattern_datetime, str(generate_datetime(each)), param, count=1) 164 | 165 | if len(noid_list): 166 | for each in noid_list: 167 | param = re.sub(pattern_noid, str(generate_noid(each)), param, count=1) 168 | 169 | if len(phone_list): 170 | for i in phone_list: 171 | param = re.sub(pattern_phone, str(generate_phone()), param, count=1) 172 | 173 | if len(guid_list): 174 | for i in guid_list: 175 | param = re.sub(pattern_guid, generate_guid(), param, count=1) 176 | 177 | if len(wxid_list): 178 | for i in wxid_list: 179 | param = re.sub(pattern_wxid, generate_wxid(), param, count=1) 180 | 181 | return param 182 | 183 | 184 | def replace(param, relevance=None): 185 | """替换参数对应关联数据 186 | 187 | :param param: 参数对象 188 | :param relevance: 关联对象 189 | :return: 190 | """ 191 | if not param: 192 | pass 193 | elif isinstance(param, dict): 194 | for key, value in param.items(): 195 | if isinstance(value, dict): 196 | param[key] = replace(value, relevance) 197 | elif isinstance(value, list): 198 | for index, sub_value in enumerate(value): 199 | param[key][index] = replace(sub_value, relevance) 200 | else: 201 | value = replace_relevance(value, relevance) 202 | value = replace_random(value) 203 | value = replace_eval(value) 204 | param[key] = value 205 | 206 | elif isinstance(param, list): 207 | for index, value in enumerate(param): 208 | param[index] = replace(value, relevance) 209 | 210 | else: 211 | param = replace_relevance(param, relevance) 212 | param = replace_random(param) 213 | param = replace_eval(param) 214 | 215 | return param 216 | 217 | 218 | if __name__ == '__main__': 219 | print('替换变量并计算表达式:', replace('$Eval(${unitCode}*1000+1)', {'unitCode': 9876543210})) 220 | print('生成1-9之间的随机数:', replace('$RandInt(1,9)')) 221 | print('生成10位随机字符:', replace('$RandStr(10)')) 222 | print('从列表中随机选择:', replace('$RandChoice(a,b,c,d)')) 223 | print('生成一个伪手机号:', replace('$GenPhone()')) 224 | print('生成一个guid:', replace('$GenGuid()')) 225 | print('生成一个伪微信ID:', replace('$GenWxid()')) 226 | print('生成一个伪身份证:', replace('$GenNoid()')) 227 | print('生成一个18岁伪身份证:', replace("$GenNoid(y-18)")) 228 | print('生成下个月今天的日期:', replace("$GenDate(m+1)")) 229 | print('生成昨天此时的时间:', replace("$GenDatetime(d-1)")) 230 | print('通过索引指定关联值:', replace('${name[-1]}', {'name': ['test1', 'test2']})) 231 | --------------------------------------------------------------------------------