preface

At the beginning of this quarter, the management of our company put forward the requirement to comprehensively improve the technical level of the department. As the most important part of the project development process — test, we also have our own technical pursuit, so in order to change the original business function test into automatic test. In the past, most of the work was done manually, using Postman and Fiddler to capture packages and intercept data. Later, after discussion, we decided to start interface automation based on Python learning. With our efforts, this automation framework has been basically completed, so I made some summaries for future review. There are many imperfect places, we can leave a message together to discuss research, common progress.

First, let’s think about the interface testing process



Second, choose the right framework

Once the process was clear, we needed to choose an appropriate framework, so Python3+requests+ UNITTest framework was chosen

The Requests module sends HTTP network Requests, including POST, GET, PUT, DELETE, and HEAD

Python +unittest unittest framework and test report generation (HTMLTestRunner)

Framework details are not described here, for requests please click here

Unittest reference click to go

Based on the above, let’s build our framework step by step. In this process, we need to separate business and data so that we can be flexible and achieve the purpose of writing the framework. Next, let’s divide the structure.

Our structure looks like this



Data: Stores data files used by automated tests

Log: stores generated log files

Base: Stores common methods

Report: Stores the generated automated test report

Testcase: stores test scripts

Next, the development of common methods

Let’s take a look at the public class or function in the Base file, which is mainly used for the subsequent call of the test case. All the public and unchanging data can be placed here, and it is also convenient to maintain

The configuration document is as follows

/data/ report_address =./report/ [HTTP] base_URL = http://xxx.xxCopy the code

Want to know how to get or write data from a configuration document? Well, keep going.

import os
import configparser

Get the current py file address
proDir = os.path.split(os.path.realpath(__file__))[0]
# combine config file address
configPath = os.path.join(proDir,"config.ini")

class ReadConfig:
    def __init__(self):
        Get the configuration file in the current path
        self.cf = configparser.ConfigParser()
        self.cf.read(configPath)

    def get_config(self,field,key):
        Get the key value from the configuration file
        result = self.cf.get(field,key)
        return result

    def set_config(self,field,key,value):
        Write configuration information to the configuration file
        fb = open(configPath,'w') self.cf. Set (field,key,value) self.cf. Write (fb) Copies the codeCopy the code

So again, where do we keep our test data? What is the value? How do I write that? How do I keep it? .

Don’t worry. Keep reading

The test data is preferentially stored in Excel or database. This section uses Excel as an example to give a brief introduction

Here we need to use two libraries for manipulating tables, XLRD data-driven read, which works on Excel documents, but XLRD cannot write data, so we introduce Xlutils data-driven read and write

The installation method can be pip3 Install XLRD or pip3 Install xlutils.

import xlrd
import xlutils.copy
from Base.readConfig import ReadConfig
import time

class ReadExcel:

    def __init__(self,section,field,sheet):
        Open the worksheet and locate it in the sheet
        data_address = ReadConfig().get_config(section,field)
        workbook = xlrd.open_workbook(data_address)
        self.table = workbook.sheets()[sheet]


    def get_rows(self):
        Get the number of excel rows
        rows = self.table.nrows
        return rows

    def get_cell(self,row,col):
        Get cell data
        cell_data = self.table.cell(row,col).value
        return cell_data

    def get_col(self,col):
        Get whole column data
        col_data = self.table.col_value(col)
        return col_data

class WriteExcel:
    def __init__(self,section,field,sheet):
        # Open the worksheet
        self.address = ReadConfig().get_config(section,field)
        self.workbook = xlrd.open_workbook(self.address)
        self.wf = xlutils.copy.copy(self.workbook)
        self.ws = self.wf.get_sheet(sheet)

    def set_cell(self,row,col,value):
        Set cell data
        self.ws.write(row,col,value)

    def save_excel(self,filename,format):
        Get the current time
        self.time = time.strftime("%Y%m%d%H%M%S", time.localtime())
        Generate file name and format
        self.report = filename + '_' +self.time + format
        # save fileSelf.wf.save (self.report) copies the codeCopy the code

Then, test the editing of the script

All ready, the following through a simple, complete code to demonstrate the public function call, the use of the framework and report generation

import unittest
import requests
from Base.readConfig import ReadConfig
from Base.readExcel import ReadExcel
from Base.readExcel import WriteExcel
# instantiation
readexcel = ReadExcel('DATABASE'.'data_address',0)
writeexcel = WriteExcel('DATABASE'.'data_address',0)

class testcase(unittest.TestCase):
    # initialization
    def setUp(self):
        # get url
        self.base_url = ReadConfig().get_config('HTTP'.'base_url')
        self.url = self.base_url + readexcel.get_cell(1,1)
        Get the request headerSelf. Headers = readexcel. Get_cell (1,4) def test_case(self): nok = 0 ner = 0# Loop read test data in Excel, verify results, and generate test report in Excel form
        for i in range(3,readexcel.get_rows()):
            Send network request, get response value
            response = requests.post(self.url, headers=self.headers,   data=readexcel.get_cell(i,4).encode('utf-8'))
            actualresult = response.json()
            Get expected results in Excel
            expectresult = eval(readexcel.get_cell(i,6))
            Get the data to validate
            key = eval(readexcel.get_cell(i, 5))
            keylen = len(key)
            j = 0
            for k in range(keylen):
                aresult = 'actualresult' + key[k]
                eresult = 'expectresult' + key[k]
                if eval(aresult) == eval(eresult):
                    # Expected results are consistent with actual results
                    j = j + 1
            if j == keylen:
                Test data execution passes
                nok = nok + 1
                writeexcel.set_cell(i, 8, 'SUCCESS')
            else:
                Test data execution failed and write actual results to Excel
                ner = ner + 1
                writeexcel.set_cell(i, 8, 'FAILURE')
                writeexcel.set_cell(i, 7, str(actualresult))
                print('the first', i + 1, 'Row use case execution failed: expected result', expectresult, 'The actual result is', actualresult)
            Save the test report
            writeexcel.save_excel('testreport'.'.xls')
            print('Total in test data', nok, 'Use Case execution passes', ner, 'Use case execution failed')

    # Release resources
    def tearDown(self):
        pass

if __name__ == '__main__':
    Build a test set
    suite = unittest.TestSuite()
    suite.addTest(testcase('test_case'))
    Create an HTML file
    filename = ReadConfig().get_config('DATABASE'.'report_address') + 'testreport.html'
    fb = open(filename,"wb")
    Execute tests and generate HTML test reports
    runner = HTMLTestRunner.HTMLTestRunner(stream = fb,description = 'Description for the interface',title = 'Automated test report of xyz')
    runner.run(suite)
    # close fileFb.close () copies the codeCopy the code

Finally, the generated HTML report



The above is the recent summary of part of the results, I hope it will be helpful to you, the follow-up will be updated in succession, also please leave a lot of messages, mutual exchanges and mutual growth