1. Description of test requirements
A series of http interface function tests on the service backend.
Input: Construct different parameter input values according to the interface description
Output: XML file
eg:http://xxx.com/xxx_product/test/content_book_list.jsp?listid=1
2. Implementation method
1. Use Python scripts to drive tests
2. Use Excel tables to manage test data, including use case management, test data entry, test result display, etc. This requires encapsulating an Excel class.
3. Call the http interface and use the API encapsulated in Python.
4. Just convert the http assembly characters required for testing
5. Set 2 checkpoints, the return value field in the XML file (obtained by parsing XML); the correctness of the XML file (file comparison)
6. The first execution test adopts a semi-automated method, that is, manually checking whether the output XML file is correct. Once it is correct, the XML file will be sealed as the expected result of the subsequent regression test. If an error is found, it will be manually corrected to the expected file. (Note that this file is not manually checked for every test, only the first time it is tested)
3. Excel table style
4. Implement the code (code is king, and it can be easily understood with comments)
1. Test framework code
#********************************************** ****************** #TestFrame.py # Author : Vince # Version: 1.1.2 # Date: 2011-3-14 # Description: Automated testing platform #************************************************ *************** import os,sys, urllib, httplib, profile, datetime, time from xml2dict import XML2Dict import win32com.client from win32com.client import Dispatch import xml.etree.ElementTree as et #import MySQLdb #Background color of test results in Excel table OK_COLOR=0xffffff NG_COLOR=0xff #NT_COLOR=0xffff NT_COLOR=0xC0C0C0 #The summary display position of test results in Excel table TESTTIME=[1, 14] TESTRESULT=[2, 14] #Excel template settings #self.titleindex=3 #Test case title row index in Excel #self.casebegin =4 #Test case start row index in Excel #self.argbegin =3 #The parameter starting column index in Excel #self.argcount =8 #Number of parameters supported in Excel class create_excel: def __init__(self, sFile, dtitleindex=3, dcasebegin=4, dargbegin=3, dargcount=8): self.xlApp = win32com.client.Dispatch('et.Application') #MS:Excel WPS:et try: self.book = self.xlApp.Workbooks.Open(sFile) except: print_error_info() print "Failed to open file" exit() self.file=sFile self.titleindex=dtitleindex self.casebegin=dcasebegin self.argbegin=dargbegin self.argcount=dargcount self.allresult=[] self.retCol=self.argbegin + self.argcount self.xmlCol=self.retCol + 1 self.resultCol=self.xmlCol + 1 def close(self): #self.book.Close(SaveChanges=0) self.book.Save() self.book.Close() #self.xlApp.Quit() del self.xlApp def read_data(self, iSheet, iRow, iCol): try: sht = self.book.Worksheets(iSheet) sValue=str(sht.Cells(iRow, iCol).Value) except: self.close() print('Failed to read data') exit() #Remove'.0' if sValue[-2:]=='.0': sValue = sValue[0:-2] return sValue def write_data(self, iSheet, iRow, iCol, sData, color=OK_COLOR): try: sht = self.book.Worksheets(iSheet) sht.Cells(iRow, iCol).Value = sData.decode("utf-8") sht.Cells(iRow, iCol).Interior.Color=color self.book.Save() except: self.close() print('Failed to write data') exit() #Get the number of use cases def get_ncase(self, iSheet): try: return self.get_nrows(iSheet)-self.casebegin + 1 except: self.close() print('Failed to obtain Case number') exit() def get_nrows(self, iSheet): try: sht = self.book.Worksheets(iSheet) return sht.UsedRange.Rows.Count except: self.close() print('Failed to obtain nrows') exit() def get_ncols(self, iSheet): try: sht = self.book.Worksheets(iSheet) return sht.UsedRange.Columns.Count except: self.close() print('Failed to obtain ncols') exit() def del_testrecord(self, suiteid): try: #Specially extracted from the For loop to improve performance nrows=self.get_nrows(suiteid) + 1 ncols=self.get_ncols(suiteid) + 1 begincol=self.argbegin + self.argcount #Improve performance sht = self.book.Worksheets(suiteid) for row in range(self.casebegin, nrows): for col in range(begincol, ncols): str=self.read_data(suiteid, row, col) #Clear actual results[] startpos = str.find('[') if startpos>0: str = str[0:startpos].strip() self.write_data(suiteid, row, col, str, OK_COLOR) else: #Improve performance sht.Cells(row, col).Interior.Color = OK_COLOR #Clear the test results in the TestResul column and set it to NT self.write_data(suiteid, row, self.argbegin + self.argcount + 1, ' ', OK_COLOR) self.write_data(suiteid, row, self.resultCol, 'NT', NT_COLOR) except: self.close() print('Clear data failed') exit() #Execute call def HTTPInvoke(IPPort, url): conn = httplib.HTTPConnection(IPPort) conn.request("GET", url) rsps = conn.getresponse() data = rsps.read() conn.close() return data #Get the basic information of the use case [Interface,argcount,[ArgNameList]] def get_caseinfo(Data, SuiteID): caseinfolist=[] sInterface=Data.read_data(SuiteID, 1, 2) argcount=int(Data.read_data(SuiteID, 2, 2)) #Get the parameter name and store it in ArgNameList ArgNameList=[] for i in range(0, argcount): ArgNameList.append(Data.read_data(SuiteID, Data.titleindex, Data.argbegin + i)) caseinfolist.append(sInterface) caseinfolist.append(argcount) caseinfolist.append(ArgNameList) return caseinfolist #Get input def get_input(Data, SuiteID, CaseID, caseinfolist): sArge='' #Parameter combination for j in range(0, caseinfolist[1]): if Data.read_data(SuiteID, Data.casebegin + CaseID, Data.argbegin + j) != "None": sArge=sArge + caseinfolist[2][j] + '=' + Data.read_data(SuiteID, Data.casebegin + CaseID, Data.argbegin + j) + ' & amp;' #Remove the trailing & amp; characters if sArge[-1:]==' & amp;': sArge = sArge[0:-1] sInput=caseinfolist[0] + sArge #Combine all parameters return sInput #Result judgment def assert_result(sReal, sExpect): sReal=str(sReal) sExpect=str(sExpect) if sReal==sExpect: return 'OK' else: return 'NG' #Write test results to file def write_result(Data, SuiteId, CaseId, resultcol, *result): if len(result)>1: ret='OK' for i in range(0, len(result)): if result[i]=='NG': ret='NG' break if ret=='NG': Data.write_data(SuiteId, Data.casebegin + CaseId, resultcol,ret, NG_COLOR) else: Data.write_data(SuiteId, Data.casebegin + CaseId, resultcol,ret, OK_COLOR) Data.allresult.append(ret) else: if result[0]=='NG': Data.write_data(SuiteId, Data.casebegin + CaseId, resultcol,result[0], NG_COLOR) elif result[0]=='OK': Data.write_data(SuiteId, Data.casebegin + CaseId, resultcol,result[0], OK_COLOR) else: #NT Data.write_data(SuiteId, Data.casebegin + CaseId, resultcol,result[0], NT_COLOR) Data.allresult.append(result[0]) #Print the current result immediately print 'case' + str(CaseId + 1) + ':', Data.allresult[-1] #Print test results def statisticresult(excelobj): allresultlist=excelobj.allresult count=[0, 0, 0] for i in range(0, len(allresultlist)): #print 'case' + str(i + 1) + ':', allresultlist[i] count=countflag(allresultlist[i],count[0], count[1], count[2]) print 'Statistic result as follow:' print 'OK:', count[0] print 'NG:', count[1] print 'NT:', count[2] #Parse XmlString and return Dict def get_xmlstring_dict(xml_string): xml = XML2Dict() return xml.fromstring(xml_string) #Parse XmlFile and return Dict def get_xmlfile_dict(xml_file): xml = XML2Dict() return xml.parse(xml_file) #Remove historical data expect[real] def delcomment(excelobj, suiteid, iRow, iCol, str): startpos = str.find('[') if startpos>0: str = str[0:startpos].strip() excelobj.write_data(suiteid, iRow, iCol, str, OK_COLOR) return str #Check each item (non-structure) def check_item(excelobj, suiteid, caseid,real_dict, checklist, begincol): ret='OK' for checkid in range(0, len(checklist)): real=real_dict[checklist[checkid]]['value'] expect=excelobj.read_data(suiteid, excelobj.casebegin + caseid, begincol + checkid) #If the check is inconsistent, write the actual result into the expect field, format: expect[real] #will return NG result=assert_result(real, expect) if result=='NG': writestr=expect + '[' + real + ']' excelobj.write_data(suiteid, excelobj.casebegin + caseid, begincol + checkid, writestr, NG_COLOR) ret='NG' return ret #Check structure type def check_struct_item(excelobj, suiteid, caseid,real_struct_dict, structlist, structbegin, structcount): ret='OK' if structcount>1: #The passed in is List for structid in range(0, structcount): structdict=real_struct_dict[structid] temp=check_item(excelobj, suiteid, caseid,structdict, structlist, structbegin + structid*len(structlist)) if temp=='NG': ret='NG' else: #The passed in is Dict temp=check_item(excelobj, suiteid, caseid,real_struct_dict, structlist, structbegin) if temp=='NG': ret='NG' return ret #Get the exception function and line number def print_error_info(): """Return the frame object for the caller's stack frame.""" try: raiseException except: f = sys.exc_info()[2].tb_frame.f_back print (f.f_code.co_name, f.f_lineno) #Test result counter, similar to Switch statement implementation def countflag(flag,ok, ng, nt): calculation = {'OK':lambda:[ok + 1, ng, nt], 'NG':lambda:[ok, ng + 1, nt], 'NT':lambda:[ok, ng, nt + 1]} return calculation[flag]()
2. Project test code
# -*- coding: utf-8 -*- #************************************************ *************** #xxx_server_case.py # Author : Vince # Version: 1.0 # Date: 2011-3-10 # Description: Content service system test code #************************************************ *************** from testframe import * from common_lib import * httpString='http://xxx.com/xxx_product/test/' expectXmldir=os.getcwd() + '/TestDir/expect/' realXmldir=os.getcwd() + '/TestDir/real/' def run(interface_name, suiteid): print '【' + interface_name + '】' + ' Test Begin,please waiting...' global expectXmldir, realXmldir #Create the expected result directory and actual result directory respectively based on the interface name expectDir=expectXmldir + interface_name realDir=realXmldir + interface_name if os.path.exists(expectDir) == 0: os.makedirs(expectDir) if os.path.exists(realDir) == 0: os.makedirs(realDir) excelobj.del_testrecord(suiteid) #Clear historical test data casecount=excelobj.get_ncase(suiteid) #Get the number of cases caseinfolist=get_caseinfo(excelobj, suiteid) #Get basic information of Case #Traverse execution cases for caseid in range(0, casecount): #Check whether to execute the Case if excelobj.read_data(suiteid,excelobj.casebegin + caseid, 2)=='N': write_result(excelobj, suiteid, caseid, excelobj.resultCol, 'NT') continue #The current Case ends and continues to execute the next Case #Get test data sInput=httpString + get_input(excelobj, suiteid, caseid, caseinfolist) XmlString=HTTPInvoke(com_ipport, sInput) #Execute the call #Get the return code and compare result_code=et.fromstring(XmlString).find("result_code").text ret1=check_result(excelobj, suiteid, caseid,result_code, excelobj.retCol) #Save the expected result file expectPath=expectDir + '/' + str(caseid + 1) + '.xml' #saveXmlfile(expectPath, XmlString) #Save the actual results file realPath=realDir + '/' + str(caseid + 1) + '.xml' saveXmlfile(realPath, XmlString) #Compare expected results and actual results ret2= check_xmlfile(excelobj, suiteid, caseid,expectPath, realPath) #Write test results write_result(excelobj, suiteid, caseid, excelobj.resultCol, ret1, ret2) print '【' + interface_name + '】' + ' Test End!'
3. Test entrance
# -*- coding: utf-8 -*- #************************************************ *************** #main.py # Author : Vince # Version: 1.0 # Date: 2011-3-16 # Description: Test assembly, use case execution entry #************************************************ *************** from testframe import * from xxx_server_case import * import xxx_server_case #Product system interface test #Set up test environment xxx_server_case.excelobj=create_excel(os.getcwd() + '/TestDir/xxx_Testcase.xls') xxx_server_case.com_ipport=xxx.com' #Add testsuite begin run("xxx_book_list", 4) #Add other suite from here #Add testsuite end statisticresult(xxx_server_case.excelobj) xxx_server_case.excelobj.close()
Summary:
Thank you to everyone who reads my article carefully! ! !
As someone who has experienced it, I also hope that everyone will avoid some detours. If you don’t want to experience the feeling of not being able to find information, no one to answer questions, and giving up after a few days of study, here I will share with you some learning about automated testing. Resources, I hope they can help you on your way forward.
How to obtain documents:
Join my software testing exchange group: 632880530 Get it for free~ (Academic exchanges with fellow experts, and live broadcasts every night to share technical knowledge points)
This document should be the most comprehensive and complete preparation warehouse for friends who want to engage in [software testing]. This warehouse has also accompanied me through the most difficult journey. I hope it can also help you!
All of the above can be shared. You only need to search the vx official account: Programmer Hugo to get it for free