Interface automation notes

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:

  1. Using unit test framework
class (Class name):
def setUP(self):
pass
def test_01(self):
print('this is test01')
def tearDown(self):
pass
  1. 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')
  1. 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...')
  1. 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
  1. 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')
  1. 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)
  1. 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()
  1. 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()
  1. 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

Tags: Python Pycharm

Posted on Sat, 09 Oct 2021 13:21:54 -0400 by Jalz