Morning in the garden, see a lot of small partners to share the knowledge of the interface test, we describe some of the experience more or less, I have encountered, suddenly realize that the accumulation of knowledge is how important, I remember my earliest contact interface test, is only in the browser to manually test the return results of a single interface, Later, using Python's unittest to write their own test framework, and now most of the small partners of the same method, the test case is also stored in the Excle table, which is OK for the single test, but if the multi-person collaborative testing, the problem comes out, Because the test cases that are stored in different excle tables by directory are cumbersome to maintain, and are not easy for multiple people to query or co-maintain test cases. So before the boss of the company to recommend a tool--fitnesse, it is to use the wiki to manage test cases on the interface, driving the background script to test, because the test case interface is a wiki address, can be very convenient to work together with everyone, and use case query and maintenance is more convenient.
or API interface test, I wrote several different demos from different angles years ago, although most people using FitNesse are now using slim engine, but because of the Java HelloWorld level I have been using Python, Unable to find the right support slim Python plugin, so still use the FitNesse fit engine, with pyfit support up.
For API interface Functional testing, I personally think there are several aspects to be concerned: interface status, Response time, field format, return data, recall before the interview Ali, referred to the interface test, he asked me a lot of HTTP protocol class, the specific problem is not clear, probably a few handshake interaction that kind of, the amount, Do not know whether it is the focus of different reasons, he asked a few questions about the interface test I have not used, in fact, I still have some doubts, do not know that he understands the interface test and I understand the deviation, but perhaps I dabble in the field is too narrow, for the interface should be how to fully test I was more skeptical, Also often on the Internet to read the documentation on the interface test, but the feeling has little effect, well, the exploration of the unknown field is still continuing, for the known areas of small fruit, take out and share with the small partners
Tested Interface: API interface, return result JSON format
Tools used: Fitnesse,fit engine, Python
The first way:
Test idea: Initialize the test data on the page, fill in the expected results by each field, and compare the actual results of the interface.
Test data preparation: Use SQL statements to initialize test data on the interface, and then included the page on the test case page
Test case: Separate the JSON fields into the test case table, using Columnfixture, the test case format is as follows
BaseURL: The basic part of the interface, this part can be parameterized outside the table and then pass the value into the table, account and password is the interface of the two input parameters, with? Identifies the result to be validated, and each field that returns the JSON result is disassembled in the table.
Background script:
Class Logintest (columnfixture): _typedict = {"description": "String", "BaseUrl": "string", "Accou NT ":" string "," Password ":" string "," status ":" Int "," Retmsg ":" string "," token ":" string ", "Uclen": "int", "Ucuserid": "int", "Ucamount": "String",} def __init__ (self): COLUMNF Ixture.__init__ (self) self.account= "self.password=" self. Baseurl= ' Self.jsondata= ' self.ret= ' def getres (self):
Url=self. baseurl+ "account=" +self.account+ "&password=" +self.password tmp=res.fetch_res (URL) result = json. Loads (TMP) return result def retmsg (self): Self.jsondata=self.getres () Self.ret=self.jsond ata["ret"] result=str (self.jsondata["ret"]) +self.jsondata["MSG"] return result def status (self): Url=self. baseurl+ "account=" +self.account+ "&password=" +self.password result=res.fetch_status (URL) return Resul T def token (self): result= "If self.ret==1:result= self.jsondata[" Data "[token] ] Return result def uclen (self): result= ' If Self.ret==1:result=len (self.js ondata["Data" ["Usercapital"]) return result def ucuserid (self): result= ' if self.ret==1: result=self.jsondata["Data" ["Usercapital"] ["userId"] return result def ucamount(self): result= ' If Self.ret==1:result=str (self.jsondata["Data" ["Usercapital"] ["Amount"] ) return result
Advantages: The test script structure is simple, the test case format is clear, the disadvantage: If the interface returns a hierarchy or a large number of fields, it is not convenient for test case maintenance, need to initialize test data and clear the increased data, some dynamic fields (such as creattime) can not accurately verify
The second way:
Test idea: On the basis of the existing database, no need to add test data each time, in the test script according to the requirements of the SQL statement to retrieve the corresponding fields of data, as expected results, and the actual results of the interface comparison
Test data: Based on existing database
Test Case:
Sample test Script section:
def retmsg (self): if Self.status==200:self.jsondata=self.getres () isusersql= "S Elect * from Hcm_user WHERE NAME like \ ' "+self.account+" \ ' and PASSWORD like \ ' "+self.password+" \ ' and Type=0 ' Self.isuser=db.querydb (Isusersql) self.ret=self.jsondata["ret"] result=str (self.jsondata["ret"]) +self.jsondata["MSG"] return result Else:return " def securitystatuscheck (self): symbol= "=" list=[' userId ', ' userName ', ' emailstatus ', ' mobilestatus ', ' re Alnameauthstatus ', ' autotransfer ', ' trusteeshipaccountstatus '] datajson=[] datacase=[] if s Elf.isuser:sql= "select A.id,a. ' Name ', if (a.email!=", 1,0), if (A. ' Mobile ', 1,0), B. ' Yeepay_account_status ', b.au To_transfer,b. ' Yeepay_account_status ' from Hcm_user a,hcm_user_auth b WHERE NAME like ' "+self.account+" ' and A.id=b.user _id " DATA=DB.QUERYDB (SQL) if data:for i in range (0,len (list)): Datacase.append (List[i]+symbol+str (Data[0][i])) if self.ret==1:tmp=self.jsondata["Data" ["s Ecuritystatus "] for I in range (0,len (list)): Datajson.append (List[i]+symbol+str (tmp[lis T[i]]) Result=check (Datajson, datacase) return result
Test results:
Suddenly found to write their own advantages and disadvantages good two Ah, anyway is the above two do not meet the requirements of the eldest brother, they hope I can write a universal framework, so that no coding ability of the person can also do interface testing, that is, only the foreground to write test cases, without the background script can be tested, so there is the following third way
The Third Way:
Test ideas: Meet the requirements of the eldest, do not write any script to interface testing
Test data: Pinning a well-initialized database
Test Case:
Where Firsturl is a dependent login interface, the URL is the test interface, blacklist is want to filter the De return field blacklist (such as Ordeid, each time is a change, can not be accurately verified, added to the blacklist can not be verified), data is the desired result, Because the tested interface needs to be logged in and then kept session in order to return to normal results, the actionfixture of fit is used here.
Sample test Script:
From fit. Fixture Import Fixture Import urllib2,cookielib,urllibimport module,jsonimport sysreload (SYS) sys.setdefaultencoding ( ' UTF-8 ') class Actiontest (Fixture): _typedict = {} def __init__ (self): #初始化参数 the fixture.__init__ (self) SEL F.__firsturl = ' #< Private attributes (Python Convention). Self.__url = ' Self.__parameter = ' self.__blacklist= ' self.__data= ' self.res= ' SE lf.status= "self.expectedlist=" self.actuallist= "self.test=" _typedict["firsturl"] = "String" def firsturl (self, s): Self.__firsturl = s _typedict["url"] = "String" def url (self, s): Self.__ur L = s _typedict["parameter"] = "Dict" def parameter (self, s): Self.__parameter = S _typedict["Blacklist"] = "List" Def blacklist (self, s): Self.__blacklist = s _typedict["data"] = "String" def data (self, s): Self.__data = s _typedict["do"] = "Default" #< Auto-detEct:none = void def do (self): #访问接口并保存结果 cookie=cookielib. Cookiejar () Opener=urllib2.build_opener (urllib2. Httpcookieprocessor (Cookie)) Try:req=opener.open (Self.__firsturl) Self.status=req.code Except Urllib2. Httperror, e:self.status= E.code if Self.status==200:for CJ in Cookie:if CJ . name== ' Jsessionid ': session= cj.value req=urllib2. Request (Self.__url) Data=urllib.urlencode (self.__parameter) try:tmp = Opener.open (re Q,data) Self.status=tmp.code except Urllib2. Httperror, E:self.status=e.code if self.status==200:self.res= tmp.read () Else:self.res= ' {"status": "No"} ' else:self.res= ' {"LoginStatus": "No"} ' _t ypedict["status"] = "Int" def status (self): return self.status _typedict["expect"] =" String "Def expect (self): #调用module函数比较测试结果 self.expectedlist=[] self.actuallist=[] Module.re Sultlist (Self.__blacklist,self.__data, Self.res, Self.expectedlist, self.actuallist) #比较后将结果存放到输出数组中 result=module. OutPut (self.expectedlist) #tmp =unicode (self.__data, ' utf-8 ') #return str (self.actuallist return Resul T _typedict["actual"] = "String" def actual (self): #调用module函数比较测试结果 result=module.output (self.actuallist) return result
Test results:
Itnesse API interface for automated test learning