Python interface to test automation from design to development

7, Excel data read

A use case is placed in Excel, with xlrd to read the data and write data need to use xluntils, install:

pip install xlrd

pip install xluntils

7.1, reads the configuration file

Read Excel data, we need to know the corresponding row and column, the column is relatively fixed, the settings defined in the configuration file, and then read, row as a parameter. Defined conf / settings file is as follows:

[excel]
case_no=0
case_name=1 is_run=2 case_level=3 case_header=4 case_cookies=5 req_type=6 case_url=7 case_body=8 expect_result=9 operator=10 actual_result=11 test_result=12

Write reading method configured unitls / load_conf.py, the method for obtaining the column value. lood_conf () function takes two arguments: a string identifier configuration items, configuration item type. For example, to read the next integer excel case_url: lood_conf ( "excel.case_url", "int"). The method of the class excel_config column value returned is defined (below).

The complete code is as follows:

import  configparser

'''
read conf from setting.conf
@:parameter:identstr,value_type
value_type:"int" or "str"
'''
def lood_conf(identstr,value_type): cf = configparser.ConfigParser() cf.read("../config/settings.conf") idenlist = identstr.split('.') if value_type == "int": try: value = cf.getint(idenlist[0],idenlist[1]) return value except (configparser.NoSectionError ,configparser.NoOptionError) as e: print(e) if value_type == "str": try: value = cf.get(idenlist[0],idenlist[1]) return value except (configparser.NoSectionError ,configparser.NoOptionError) as e: print(e) ''' 获取url,request body等的列号 ''' class excel_config(): #获取用例编号的列 def caseno_col(self): return lood_conf("excel.case_no","int") def casename_col(self): return lood_conf("excel.case_name","int") def isrun_col(self): #print(lood_conf("excel.is_run","int")) return lood_conf("excel.is_run","int") def level_col(self): return lood_conf("excel.case_level","int") def header_col(self): return lood_conf("excel.case_header","int") def cookies_col(self): return lood_conf("excel.case_cookies","int") def reqtype_col(self): return lood_conf("excel.req_type","int") def caseurl_col(self): return lood_conf("excel.case_url","int") def casebody_col(self): return lood_conf("excel.case_body","int") def expectresult_col(self): return lood_conf("excel.expect_result","int") def actualresult_col(self): return lood_conf("excel.actual_result","int") def testresult_col(self): return lood_conf("excel.test_result","int") def test_operator_col(self): return lood_conf("excel.operator","int") 

7.1, write Excel class operation

unitls / excel_tool.py cases pick-defined number, name, etc. The method of use cases, need to pass line. Write-back test result, actual results write back method requires two arguments: OK, value. The complete code is as follows:

#coding:utf-8
import xlrd
from untils.log_trace import *
from xlutils.copy import copy
from untils.load_conf import excel_config

class excel_tool():

    def __init__(self,excel_name): self.curr_excel = xlrd.open_workbook(excel_name) self.table = self.curr_excel.sheet_by_index(0) #print(self.table.cell(1,1).value) #实例化excel_config self.config = excel_config() self.rows = self.table.nrows self.excel_name = excel_name #获取用例编号 def get_caseno(self,row): caseno = self.table.cell(row,self.config.caseno_col()).value if caseno: return caseno else: logging.info("case no is null") return None #获取用例名称 def get_casename(self,row): casename = self.table.cell(row,self.config.casename_col()).value return casename #获取是否运行标志 def get_runflag(self,row): run_flag = self.table.cell(row,self.config.isrun_col()).value return run_flag #获取用例级别 def get_caselevel(self,row): caselevel = self.table.cell(row,self.config.level_col()).value return caselevel #获取请求url def get_caseurl(self,row): caseurl = self.table.cell(row,self.config.caseurl_col()).value return caseurl #获取请求body def get_casebody(self,row): case_body = self.table.cell(row,self.config.casebody_col()).value return case_body #获取header def get_headerflag(self,row): headerflag = self.table.cell(row,self.config.header_col()).value return headerflag #获取coocikes def get_cookiesflag(self,row): cookiesflag = self.table.cell(row,self.config.cookies_col()).value return cookiesflag #获取请求类型 def get_methodtype(self,row): method_type = self.table.cell(row,self.config.reqtype_col()).value return method_type #获取预期结果 def get_expectres(self,row): expect_res = self.table.cell(row,self.config.expectresult_col()).value return expect_res #获取测试结果 def get_testres(self,row): test_res= self.table.cell(row,self.config.testresult_col()).value return test_res #获取操作符 def get_operator(self,row): operator = self.table.cell(row,self.config.test_operator_col()).value return operator #回写测试结果到excel def write_testres(self,row,value): wbook = copy(xlrd.open_workbook(self.excel_name)) sheet = wbook.get_sheet(0) sheet.write(row, self.config.testresult_col(), value) wbook.save(self.excel_name) #回写实际结果 def write_actualres(self,row,value): wbook = copy(xlrd.open_workbook(self.excel_name)) sheet = wbook.get_sheet(0) sheet.write(row, self.config.actualresult_col(), value) wbook.save(self.excel_name) 

8, the assembly of cases

With Excel-based operation, it can be easily read data and backfill the results. Next, in unitls / run_main.py assembled with the embodiment. Prior to assembly, to obtain flag run:

  • Run flag is N, without assembling the cases marked with skiiped, backfill the test results into Excel.
  • Run flag is Y, and executes the use case began to assemble, and compare the expected and actual results.
  • Performed by use cases, the cases marked with Pass, backfill testing and actual results, the actual result is returned interface.
  • Use case on failure cases use labeled failed, backfill testing and actual results.

Interfaces need to use authentication headers, to write died in run_main.py, this problem is solved later, in the above process, the need to increase logging, easy to locate the problem and view a running log of the use case. The complete code is as follows:

#coding:utf-8
from untils.excel_tool import excel_tool
from untils.send_request import send_request
from untils.log_trace import *
from untils.check_result import CheckResult
import  json
headers = {
    "X-Token":"0a6db4e59c7fff2b2b94a297e2e5632e"
}

class runner(): def __init__(self): self.excel = excel_tool("../testcase/test.xls") self.check = CheckResult() def join_case(self): global skip_list,sucess_list,failed_list,skip_list sucess_list = [] sucess_list = [] failed_list = [] skip_list = [] for row in range(1,self.excel.rows): no = self.excel.get_caseno(row) url = self.excel.get_caseurl(row) isrun = self.excel.get_runflag(row) name = self.excel.get_casename(row) level = self.excel.get_caselevel(row) data = self.excel.get_casebody(row) expect_res = self.excel.get_expectres(row) method = self.excel.get_methodtype(row) hasheader = self.excel.get_headerflag(row) operator = self.excel.get_operator(row) if isrun == "Y": logging.info("Begin to run test case : %s,case number :%s" %(name,no)) logging.info("Request method type is :%s" %method) logging.info("Request URL:%s" %url) logging.info("Request Body:%s" %json.dumps(json.loads(data),sort_keys=True,indent=2)) res = send_request(method,url,data=data,headers=headers) is_sucess = self.check.cmpdict(eval(expect_res),eval(res.text),operator) print(is_sucess) if is_sucess: sucess_list.append(name) #回写测试结果 self.excel.write_testres(row,"pass") #回写实际结果 self.excel.write_actualres(row,res.text) logging.info("Test case %s run sucess." %name) else: failed_list.append(name) print("fail",is_sucess) #回写测试结果 self.excel.write_testres(row,"failed") #回写实际结果 self.excel.write_actualres(row,res.text) logging.error("Test case %s run fail." %name) logging.info("Response is:%s" %json.dumps(res.json(),sort_keys=True,indent=2)) else: skip_list.append(name) self.excel.write_testres(row,"skipped") def sum(self): total = len(sucess_list)+len(failed_list) + len(skip_list) failed = len(failed_list) sucess = len(sucess_list) logging.info("-----------------------------------------------------------") logging.info("本次一共运行:%s 个用例" %total) logging.info("本次运行通过:%s 个用例" %sucess) logging.info("本次运行跳过:%s 个用例" %len(skip_list)) logging.info("跳过的用例:%s" %skip_list) logging.info("-----------------------------------------------------------") 

9, with the results of Examples checking operation

In untils / run_main.py method cmpdict () is used to verify the expected and actual results matches, it requires three arguments: the expected result dictionary, a dictionary, actual, operator. Methods prepared in Example check_result.py the check result. Currently supports only two operators, equal and notequal, expected results for the dictionary, which can not be nested dictionary. And complete code is as follows:

from untils.log_trace import *
class  CheckResult():
    def dict_value(self,key,actual):
        try:
            if key in actual: return actual[key] else: for keys in actual: return self.dict_value(key,actual[keys]) except Exception as e: logging.error(e) return None def cmpdict(self,expect,actual,equal): logging.info("Begin to check result of testcase.") is_dict = isinstance(expect,dict) and isinstance(actual,dict) if is_dict: if equal == "equal": for key in expect.keys(): if expect[key] == self.dict_value(key,actual): logging.info("%s is equal to %s" %(expect[key],self.dict_value(key,actual))) return True else: logging.error("%s is not equal to %s" %(expect[key],self.dict_value(key,actual))) return False if equal == "notequal": for key in expect.keys(): if key != self.dict_value(key,actual): logging.info("%s is not equal to %s" %(expect[key],self.dict_value(key,actual))) return True else: logging.error("%s is equal to %s" %(expect[key],self.dict_value(key,actual))) return False else: logging.error("Operator :%s is not support now,you can define it in file[check_result.py]" %equal) else: logging.error("Expect or actual result is not dict,check it in excel. ")

10, operated with cases

Create a name for test.xls of Excel, place it under testcase path, and preparation of test cases in Excel. Please refer interface development: using the Django development a simple interface: CRUD article , for example, I am going to use:

Import run_mian module untils / untils_test.py to test it:

from untils.run_main import runner
if __name__ == "__main__":
    #test_send_request() runner = runner() runner.join_case() runner.sum()

Run untils_test.py, then go to Excel to view the results:

See the path test report operation logs as follows:

Sat, 11 May 2019 19:37:56 INFO check_result.py [line:16]  Begin to check result of testcase. Sat, 11 May 2019 19:37:56 ERROR check_result.py [line:38] Operator :e1qual is not support now,you can define it in file[check_result.py] Sat, 11 May 2019 19:37:56 INFO run_main.py [line:37] Begin to run test case : 查询文章,case number :1.0 Sat, 11 May 2019 19:37:56 INFO run_main.py [line:38] Request method type is :GET Sat, 11 May 2019 19:37:56 INFO run_main.py [line:39] Request URL:http://127.0.0.1:9000/articles Sat, 11 May 2019 19:37:56 INFO run_main.py [line:40] Request Body:{} Sat, 11 May 2019 19:37:56 INFO send_request.py [line:25] {'X-Token': '0a6db4e59c7fff2b2b94a297e2e5632e'} Sat, 11 May 2019 19:37:56 INFO check_result.py [line:16] Begin to check result of testcase. Sat, 11 May 2019 19:37:56 INFO check_result.py [line:22] BS.200 is equal to BS.200 Sat, 11 May 2019 19:37:56 INFO run_main.py [line:52] Test case 查询文章 run sucess. Sat, 11 May 2019 19:37:56 INFO run_main.py [line:62] Response is:{ "all_titles": { "Hello": "alive", "amy1": "alive", "modifytest": "alive", "useasge of ddt": "alive" }, "msg": "query articles sucess.", "status": "BS.200" } Sat, 11 May 2019 19:37:56 INFO run_main.py [line:37] Begin to run test case : 新增文章,case number :2.0 Sat, 11 May 2019 19:37:56 INFO run_main.py [line:38] Request method type is :POST Sat, 11 May 2019 19:37:56 INFO run_main.py [line:39] Request URL:http://127.0.0.1:9000/articles/ Sat, 11 May 2019 19:37:56 INFO run_main.py [line:40] Request Body:{ "content": "useasge of ddt", "title": "useasge of ddt" } Sat, 11 May 2019 19:37:56 INFO send_request.py [line:25] {'X-Token': '0a6db4e59c7fff2b2b94a297e2e5632e'} Sat, 11 May 2019 19:37:56 INFO check_result.py [line:16] Begin to check result of testcase. Sat, 11 May 2019 19:37:56 ERROR check_result.py [line:25] BS.200 is not equal to BS.400 Sat, 11 May 2019 19:37:56 ERROR run_main.py [line:60] Test case 新增文章 run fail. Sat, 11 May 2019 19:37:56 INFO run_main.py [line:62] Response is:{ "msg": "title aleady exist,fail to publish.", "status": "BS.400" } Sat, 11 May 2019 19:37:56 INFO run_main.py [line:37] Begin to run test case : 修改文章,case number :3.0 Sat, 11 May 2019 19:37:56 INFO run_main.py [line:38] Request method type is :POST Sat, 11 May 2019 19:37:56 INFO run_main.py [line:39] Request URL:http://127.0.0.1:9000/articles/7 Sat, 11 May 2019 19:37:56 INFO run_main.py [line:40] Request Body:{ "content": "modify test", "title": "modify test" } Sat, 11 May 2019 19:37:56 INFO send_request.py [line:25] {'X-Token': '0a6db4e59c7fff2b2b94a297e2e5632e'} Sat, 11 May 2019 19:37:57 INFO check_result.py [line:16] Begin to check result of testcase. Sat, 11 May 2019 19:37:57 ERROR check_result.py [line:25] BS.200 is not equal to BS.300 Sat, 11 May 2019 19:37:57 ERROR run_main.py [line:60] Test case 修改文章 run fail. Sat, 11 May 2019 19:37:57 INFO run_main.py [line:62] Response is:{ "msg": "article is not exists,fail to modify.", "status": "BS.300" } Sat, 11 May 2019 19:37:57 INFO run_main.py [line:37] Begin to run test case : 删除文章,case number :4.0 Sat, 11 May 2019 19:37:57 INFO run_main.py [line:38] Request method type is :DELETE Sat, 11 May 2019 19:37:57 INFO run_main.py [line:39] Request URL:http://127.0.0.1:9000/articles/7 Sat, 11 May 2019 19:37:57 INFO run_main.py [line:40] Request Body:{} Sat, 11 May 2019 19:37:57 INFO send_request.py [line:25] {'X-Token': '0a6db4e59c7fff2b2b94a297e2e5632e'} Sat, 11 May 2019 19:37:57 INFO check_result.py [line:16] Begin to check result of testcase. Sat, 11 May 2019 19:37:57 ERROR check_result.py [line:25] BS.200 is not equal to BS.300 Sat, 11 May 2019 19:37:57 ERROR run_main.py [line:60] Test case 删除文章 run fail. Sat, 11 May 2019 19:37:57 INFO run_main.py [line:62] Response is:{ "msg": "article is not exists,fail to delete.", "status": "BS.300" } Sat, 11 May 2019 19:37:57 INFO run_main.py [line:74] ----------------------------------------------------------- Sat, 11 May 2019 19:37:57 INFO run_main.py [line:75] 本次一共运行:5 个用例 Sat, 11 May 2019 19:37:57 INFO run_main.py [line:76] 本次运行通过:1 个用例 Sat, 11 May 2019 19:37:57 INFO run_main.py [line:77] 本次运行跳过:1 个用例 Sat, 11 May 2019 19:37:57 INFO run_main.py [line:78] 跳过的用例:['新增文章缺少title'] Sat, 11 May 2019 19:37:57 INFO run_main.py [line:79] ----------------------------------------------------------- 

11 Summary

Framework finally run up, but still many problems left.

  • Many local code is not robust optimization slowly behind this. Example check operator support also use less.
  • Send e-mail module to be done.
  • Headers how to solve the problem?
  • If the requested body more, written in Excel is not very beautiful it? This can be done from a fixed place to read the file.
  • Excel, there is no mandatory test it? This can be carried out before running the check result, required missing, do not run.
  • The most crucial point, if the second use case is dependent on first use case of return, the use case has been a sore point dependent, Next resolved.

Guess you like

Origin www.cnblogs.com/cs1188/p/11516946.html