Original address: Interface automation notes
to configure:
Install the requests third-party library in pycharm
Open the DOS command or enter pip install requests in pycharm's terminal to install
Installing pyyaml 5.3.1 third party libraries
Open the DOS command or enter pip install pyyaml installation in pycharm's terminal
Syntax:
- Using unit test framework
class (Class name): def setUP(self): pass def test_01(self): print('this is test01') def tearDown(self): pass
- Skip use case
#If you want to skip a use case, just add * * * * @unittest.skip in front** # @unittest.skip #Skip this use case def test_02(self): print('this is test02') def test_03(self): print('this is test03')
- Output only at the beginning and end, and no longer output in each case run
@classmethod def setUpClass(cls): print('this is start...') @classmethod def tearDownClass(cls): print('this is end...')
- Assert
**self.assertIn('Expected results****',res.text)**
If the assertion result is inconsistent with the actual result, the following situation will appear. Click to view the difference
Expected results on the left, actual results on the right
5. Set the global variable global
Set a cookie global variable in the login interface, and it can be used in the interface below
global cok cok=res.cookies
- Import case:
First create a Python Package named case in the project, and then create a file with the suffix. yaml,
Then write the use case in the file in the format:
Url: website #The colon of each parameter name should be followed by a space followed by the parameter value method: Request mode Detil: Description (optional) data: Parameter name: Parameter value (without quotation marks) check:
- Expected result (- space after)
For example:
url: http://192.168.2.110/geeknet/flow.php?step=add_to_cart method: POST Detil: add to cart data: goods: '{"quick":1,"spec":[],"goods_id":62,"number":"1","parent":0}' check: #Expected results - one_step_buy - url: http://192.168.2.110/geeknet/flow.php?step=cart method: GET data: check:
- Shopping cart (1)
Add @ ddt.ddt before the class, and then add @ ddt.file before the function to be introduced_ Data (R 'storage path of case file'), such as
@ddt.file_data(r'D:\python\jiekou0518\case\api.yaml')#Add r to prevent path transfer
Then use in the function, such as:
def test_one(self,**test_data): url=test_data.get('url')
- How to connect to the database
(1) Create a new python package config, and then create a config.ini file in it to write the connection configuration of the database: which MySQL connection, host, port number, user name, password, library name and coding method:
[MYSQL] host = 192.168.2.110 port = 3306 user = root passwd = root db = gk charset = utf8
(2) Create a Python file configmysql in the common folder to configure the connection to the database
#Configure mysql import pymysql import configparser config = configparser.ConfigParser() #Read configuration file config.read(r'D:\python\jiekou0518\config\config.ini') class ApiTools(): #Define functions to connect to the database def conn_mysql(self): host = config.get('MYSQL','host') port = config.get('MYSQL','port') user = config.get('MYSQL','user') passwd = config.get('MYSQL','passwd') db = config.get('MYSQL','db') charset = config.get('MYSQL','charset') self.connect = pymysql.connect( host = host, port = int(port), user = user, passwd = passwd, db = db, charset = charset, ) #Connect the cursor in the database to execute sql statements self.cursor = self.connect.cursor() # Define functions to execute MySQL. There are different methods in different scenarios def execute_sql(self,sql): ''' implement sql Statement, including updating and adding data ''' self.conn_mysql() #Connect to database and get cursor self.cursor.execute(sql) #Execute sql statement with cursor self.connect.commit() #Submit after execution def search_sql(self,sql): ''' Execute query statement ''' self.conn_mysql() self.cursor.execute(sql) return self.cursor.fetchall() #Returns the value of all rows #Define functions to close sql connections to avoid occupying server resources def close_sql(self): ''' Close cursor and database connection ''' self.cursor.close() self.connect.close() #Idempotent shall be tested for the tested interface to prevent repeated submission if __name__ == '__main__': too = ApiTools() too.conn_mysql() sql = 'delete from gk_order_info WHERE zipcode =457100;' api = too.execute_sql(sql) too.close_sql() print(api)
- Finally, a tearDownClass function is added in the runfile file to delete the dirty data (useless) after the use case is executed
@classmethod def tearDownClass(cls): too = configmysql.ApiTools() too.conn_mysql() sql = "delete from gk_order_info where order_sn in(select o.order_sn from " \ "(select order_sn from gk_order_info order by add_time desc limit 1) as o)" too.execute_sql(sql) too.close_sql()
- Finally, print out the report of the use case and use unittest**** Makesuite (class name) * * * * all classes of the main function can be added to the test set
if __name__=='__main__': # unittest.main() su=unittest.TestSuite() #Build test set su.addTest(unittest.makeSuite(Test)) #Add all use cases in the main function now=time.strftime('%Y-%m-%d %H-%M-%S') #Use the current time and format the time as year, month, day, hour, minute and second filename = r'D:\python\jiekou0518\report\ '+ now +'resuilt.html' fp=open(filename,'wb') runner=HTMLTestRunner(stream=fp,title='Automated test report',description='Use case description') runner.run(su) fp.close()
Runfile case:
import unittest import ddt,time,requests from common import configmysql from HTMLTestRunner import HTMLTestRunner @ddt.ddt class Test(unittest.TestCase): @classmethod def setUpClass(cls): #Before all use cases are executed, execute the logged in use cases to obtain cookies url='http://192.168.2.110/geeknet/user.php' data={ 'username':'lee000000', 'password':'000000', 'act':'act_login', 'back_act':'http://192.168.2.110/geeknet/', 'submit':'' } res=requests.post(url=url,data=data) cls.assertIn(cls,'Welcome back',res.text) global cok cok=res.cookies @ddt.file_data(r'D:\python\jiekou0518\case\api.yaml')#Add r to prevent path transfer def test_one(self,**test_data): url=test_data.get('url') method=test_data.get('method') detil=test_data.get('detil') data=test_data.get('data') check=test_data.get('check') if method=='GET': #Convert to text format to facilitate later assertion res=requests.get(url=url,cookies=cok).text elif method=='POST': res=requests.post(url=url,data=data,cookies=cok).text # for I in check: # try: # self.assertIn(i,res) # print(i, 'use case execution succeeded') # except Exception as e: # print(i, 'use case execution failed') for I in check: self.assertIn(i,res) @classmethod def tearDownClass(cls): too = configmysql.ApiTools() too.conn_mysql() sql = "delete from gk_order_info where order_sn in(select o.order_sn from " \ "(select order_sn from gk_order_info order by add_time desc limit 1) as o)" too.execute_sql(sql) too.close_sql() if __name__=='__main__': # unittest.main() su=unittest.TestSuite() #Build test set su.addTest(unittest.makeSuite(Test)) #Add all use cases in the main function now=time.strftime('%Y-%m-%d %H-%M-%S') #Use the current time and format the time as year, month, day, hour, minute and second filename = r'D:\python\jiekou0518\report\ '+ now +'resuilt.html' fp=open(filename,'wb') runner=HTMLTestRunner(stream=fp,title='Automated test report',description='Use case description') runner.run(su) fp.close()
- How to send a test report to a designated person by mail
When Config.ini configures mail as 163 mailbox, the password is not a login password, but an authorization code
(1) Add mailbox configuration in config.ini configuration file:
[email] smtpserver = smtp.163.com sender = luokuo8080@163.com password = luokuo8080 receive = luokuo1018@163.com
(2) Add the configmail.py file in the common package. Write code to send mail
import configparser import os import smtplib from email.mime.text import MIMEText from email.header import Header config = configparser.ConfigParser() config.read(r'D:\python\jiekou0518\config\config.ini') class Send_mail: #We need to send the latest test report to our function first def send_email(self,new_report): #parm new_report is to send the latest test report found as email content f = open(new_report,'rb') body = f.read() f.close() smtpserver = config.get('email','smtpserver') #Extract the parameters of email from the config.ini file sender = config.get('email','sender') password = config.get('email','password') receive = config.get('email','receive') subject = 'API TEST Automated test report lee' #Define title msg = MIMEText(body,'html','utf-8') msg['from'] = sender msg['to'] = receive msg['subject'] = Header(subject,'utf-8') smtp = smtplib.SMTP() #Instantiate smtp (method of sending mail) smtp.connect(smtpserver) #Connect to smtp server smtp.login(sender,password) #Sign in smtp.sendmail(sender,receive,msg.as_string()) #send out smtp.quit() #sign out def latest_report(self,report_dir): #:param report_dir: pass in the path where the report is stored for filtering the newly generated test report #report_dir: pass in the path where the report is stored lists = os.listdir(report_dir) #Enumerate reports_ All file results under dir are returned as a list #Sort the list (from small to large by default) lists.sort(key = lambda fn:os.path.getmtime(report_dir + '\\' +fn)) #os.path.getmtime is the last modification time to get the file #os.path.join path splicing file = os.path.join(report_dir,lists[-1]) #That is, file ='d: \ Python \ jiekou0518 \ report \ 2020-05-20 10-46-05resume. HTML ' return file if __name__ == '__main__': mail = Send_mail() report_dir = r'D:\python\jiekou0518\report' new_report = mail.latest_report(report_dir) mail.send_email(new_report) (3)stay runfile The function of sending the mail is sent and the test report is sent to the specified mailbox. #First introduce the classes in the configmail file from common.configmail import Send_mail #Then call mail = Send_mail() report_dir = r'D:\python\jiekou0518\report' new_report = mail.latest_report(report_dir) mail.send_email(new_report)
Briefly, how do you do automation?
We use a small automation interface written in python
The python+unittest+yaml+request+ddt framework is used to write the interface automation script.
Generally, we will put the test cases of interface automation into yaml file according to the format
Then put some fixed configuration files into the config.ini file, such as the IP address, account and password, port of the database, database name of the database to be connected, etc. if you need to call the configuration in config.ini, you can get the contents in the configuration file by instantiating configparser, and then we will write some frequently used tools, Put it in tools, such as the functions to connect to the database, including the functions to submit sql statements and query statements and close the database connection. Put them in the configmysql file, and then when we test, we will write our main method in the runmain.py file, and then use the request method to reconstruct the get and post requests in this file. We will first use ddt.file_data introduces the yaml file path, and then defines a function to pass the url, method, request parameters and expected results of the test case through * * test_ After the data is transferred in, it is sent to get one by one. Then, use the if statement to judge the get request or post request, and use the request to send the request. Then use the for loop to loop out the checkpoint and assert, and use the try method to process the exception information. After execution, we can call the database processing method to clean up the data, Finally, send the test report with HtmlTestrunner.
How to test dependent interfaces?
For dependent interfaces, we usually give the return value of the previous interface to an intermediate variable return, and
And set this variable as a global variable. If the next interface uses to directly call this global variable, it is OK.
How to test the interface that needs to be logged in?
Generally, we use the unittest framework for the login interface
Then we can put the interface to be logged in into setupclass, and then give the cookie value to one
The intermediate variable, and then the intermediate variable global into a global variable, and then the following interface if you need a cookie
When receiving the request, you can directly pass in the cookie of the global variable.
Where are the test cases?
Our test cases are managed in yaml files and maintained in yaml files
Then, when using the test cases inside, we can use DDT for data-driven, using ddt.file_data
Bring in the path of yaml file, and then use the get method to obtain the field name of each field in yaml file
Then construct the request.
How to clean up the garbage data generated by the interface?
Connect the database with python to add, delete, modify and query. Pre operation of test cases, data preparation with setUp, such as login. After the test, tearDown connects to the database for data cleaning
How does python connect to the database (mysql)?
Connect to the database by importing the pymysql package
You need to use the get method through the configparser to get the information in the config.ini configuration file
Database parameters such as port, user, passwd, db name and charset encoding method
Then use pymsql.connect method to pass in the parameters to connect to the database and obtain the database cursor
Then use the execute method of the cursor to execute sql and the commit method to submit data. If yes
The queried data needs to get all the data through cursor.fetchall() and return the data,
Finally, close the cursor and close the connection.
**Script structure:** **— api.yaml** **Store interface test cases** **— config.ini** **Storage database connection configuration** **deposit email Configuration of connections** **— common** **—configmysql.py** **Method of constructing database connection** **Construct database execution( execute_sql)** **/Inquiry(****search_sql****)** **/Close database connection(****close_sql****)** **--configemail.py** **Send mail** **-- runmain.py** **Main method**
Blog source: Blog on rainy night