Interface automation test (Python+Requests+Unittest)

(1) The significance of interface automation test and the idea of separation of front and back ends

Advantages and disadvantages of interface automation test:

advantage:

1. Test reusability.

2. The maintenance cost is lower than that of UI automation.

Why? UI Higher automated maintenance costs?
Because the front page changes too fast, and UI Automation is time-consuming (for example, it takes time to wait for page elements to load, add waiting time, locate elements, operate elements, and simulate page actions)

Why is the cost of interface automation low?
Because the interface is relatively stable, the response time of the interface is basically seconds and milliseconds, and the speed is fast. Moreover, the interface automation itself can also do some related operations and whole process operations (such as registration) --> Sign in --> Modify personal information).

3. Easy to return.

4. You can run more and more cumbersome tests. An obvious benefit of automation is that more tests can be run in less time.

Advantages 1, 3 and 4 are interface automation and UI Advantages of automation.

Disadvantages:

1. It cannot completely replace manual testing. (automation can never replace manual testing, but only improve testing efficiency)

2. Manual testing finds more defects than automated testing, and automated testing is not easy to find new bugs.

Difference between GET request and POST request:

1. Generally, the GET request is to obtain data from the background server for the display of the front-end page (for example, see the list page), and the POST request is to transmit data to the server (login, registration, uploading files, publishing articles). When to use GET and when to use POST depends on development. Whether POST request or GET request is used, data addition, deletion, modification and query can be completed. Different request methods are more an agreement.

2. The request parameters of the GET request are spliced behind the url and can only be transmitted in the form of text. The request parameters will be displayed in the address bar. The data length is limited by the length of the url, and the amount of data transmitted is small (about 4KB, which will vary from browser to browser). The request parameters of the POST request are placed in the request body, and the amount of data transmitted is large (8M by default), There is no requirement for data length. GET requests can be accessed directly in the browser, while POST requests can only be completed with tools (such as postman and jmeter).

Fast GET request speed and low security; POST requests are generally used in situations with high security requirements such as login. The requests will not be cached or retained in the browser's history.

Previously: get Query; post newly added; put Editing; delete delete
 Now? get Query; post newly added + edit + delete
 Or: pure post Walk the world

Front and rear end separation

Development mode

The old way:

  • Product Manager / Leader / customer puts forward requirements (puts forward written requirements)
  • Make design drawings for UI
  • Front end engineers make html pages (pages that users can see)
  • The back-end engineer sets the html page into a jsp page (the front and back ends are strongly dependent, and the back-end must wait until the front-end html page is ready to set the jsp. If the html changes, it will be very troublesome and the development efficiency is low)
  • There is a problem with the integration
  • Front end rework
  • Back end rework
  • Secondary integration
  • Successful integration
  • deliver

New ways:

  • Product Manager / Leader / customer puts forward requirements (puts forward written requirements)
  • Make design drawings for UI
  • Agreed interface & Data & parameters at front and back end
  • Front and back end parallel development (without strong dependence, front and back end parallel development can be used. If the requirements change, as long as the interface & parameters remain unchanged, there is no need to modify the code on both sides, and the development efficiency is high)
  • Front and rear integration
  • Front page adjustment
  • Successful integration
  • deliver

🤑 Open the browser developer tool through F12 to capture packets. The returned data is in json format, that is, the front and back ends are separated. When returning, the html page is not separated from the front and back ends.

Concept of microservice:

Divide large modules into small modules. Reduce the coupling degree of code, so as to reduce the impact between modules. Originally, a jar package contains all modules. Changing one module may affect other modules. Now it is to break one module into one jar package. The interaction between modules is through the interface. If there is a problem with which module, you only need to modify the jar package of that module to avoid errors in other modules caused by modifying the code of one module.

(2) Explanation of Python requests framework

Establishment of interface automation requests environment

Interface automation core library: requests

How to install the requests Library:

Method 1:

Command line installation, open cmd or terminal, and enter the following command:

pip install requests -i https://pypi.douban.com/simple/

Method 2:

Install in pycharm, settings -- > Project -- > project interpreter -- > click the "+" sign -- > enter the request to install

Is the test environment ok

import requests

url_toutiao = "https://www.ixigua.com/tlb/comment/article/v5/tab_comments/?tab_index=0&count=10&group_id=6914830518563373581&item_id=6914830518563373581&aid=1768"
# Mode 1:
# result_toutiao = requests.get(url_toutiao)

# Mode 2:
result_toutiao = requests.get(url=url_toutiao)

# Mode 3:
# result_toutiao = requests.get(
#     "https://www.ixigua.com/tlb/comment/article/v5/tab_comments/?tab_index=0&count=1&group_id=6914830518563373581&item_id=6914830518563373581&aid=1768")

# print(result_toutiao.json())
# print(type(result_toutiao.json()))  # <class 'dict'>
result = result_toutiao.json()
print(result)
expect_result = "Brilliance golden cup car flower after flower"
actual_result = result["data"][0]["comment"]["user_name"]
print(actual_result)
if expect_result == actual_result:
    print("pass!")
else:
    print("failed!")

Response timeout

import requests

# V tribe: http: / / [server ip]:8081/index.html
# Article list
url_v_article = "http://[server ip]:8081/article/all“
v_headers = {
    "Cookie": "studentUserName=ctt01; Hm_lvt_cd8218cd51f800ed2b73e5751cb3f4f9=1609742724,1609762306,1609841170,1609860946; adminUserName=admin; JSESSIONID=9D1FF19F333C5E25DBA60769E9F5248E"}
article_params = {"state": 1,  # -1: All articles 1: Published 0: recycle bin 2: draft box
                  "page": 1,  # Show page 1
                  "count": 6,  # 6 per page
                  "keywords": ""  # Keywords included
                  }
keywords = ["Big orange cat", "Running man", "tooth"]
for keyword in keywords:
    article_params["keywords"] = keyword
    # headers and params are of indefinite length and pass parameters according to the defined dictionary
    # Timeout timeout in seconds
    # By setting the timeout, tell the requests how long to stop waiting for a response
    result = requests.get(url_v_article, headers=v_headers, params=article_params, timeout=30)
    print(result.json())

JSON,URL,text,encoding,status_code,encoding,cookies

print(result.json()) # The response results are printed out in json
print(result.url) # Print url address
print(result.text) # Print the contents of the server response in text format
print(result.status_code) # Response status code
print(result.encoding) # Coding format
print(result.cookies) # cookie

JSON (JavaScript object notation) is a lightweight data exchange format. It is based on ECMAScript (js specification formulated by the European Computer Association) It uses a text format completely independent of the programming language to store and represent data. The concise and clear hierarchical structure makes JSON an ideal data exchange language. It is easy for people to read and write, easy for machine parsing and generation, and effectively improves the efficiency of network transmission.

JSON format is equivalent to dictionary type in Python.

JSON formatting: http://www.bejson.com/jsonviewernew/

url online encoding conversion: https://www.w3cschool.cn/tools/index?name=urlencode_decode

(3) Automatic implementation of get, post, put and delete requests

GET request mode

import requests

url_toutiao = "https://www.ixigua.com/tlb/comment/article/v5/tab_comments/?tab_index=0&count=10&group_id=6914830518563373581&item_id=6914830518563373581&aid=1768"
# Mode 1:
# result_toutiao = requests.get(url_toutiao)

# Mode 2:
result_toutiao = requests.get(url=url_toutiao)

# Mode 3:
# result_toutiao = requests.get(
#     "https://www.ixigua.com/tlb/comment/article/v5/tab_comments/?tab_index=0&count=1&group_id=6914830518563373581&item_id=6914830518563373581&aid=1768")

# print(result_toutiao.json())
# print(type(result_toutiao.json()))  # <class 'dict'>
result = result_toutiao.json()
print(result)
expect_result = "Brilliance golden cup car flower after flower"
actual_result = result["data"][0]["comment"]["user_name"]
print(actual_result)
if expect_result == actual_result:
    print("pass!")
else:
    print("failed!")
    
Operation results:
{'message': 'success', 'err_no': 0, 'data': [{'comment': {'id': 6914864825282215951, 'id_str': '6914864825282215951', 'text': 'There are many people working abroad in Gaocheng. Focus on checking Gaocheng district!', 'content_rich_span': '{"links":[]}', 'user_id': 940799526971408, 'user_name': 'Brilliance golden cup car flower after flower',}, 'post_count': 0, 'stick_toast': 1, 'stable': True}
Brilliance golden cup car flower after flower
pass!

POST request mode

import requests

url_v_login = "http://[server ip]:8081/login“
# Define parameters, dictionary format
payload = {'username': 'sang', 'password': '123'}
# Content-Type: application/json --> json
# Content-Type: application/x-www-form-urlencoded --> data
result = requests.post(url_v_login, data=payload)
# Convert the returned result to json format
result_json = result.json()
print(result_json)  # {'status':' success', 'MSG': 'login succeeded'}
# Get requestscookeiejar
result_cookie = result.cookies
print(result_cookie, type(result_cookie))  # RequestsCookieJar
# Convert requestscookeiejar to dictionary format
result_cookie_dic = requests.utils.dict_from_cookiejar(result_cookie)
print(result_cookie_dic)  # {'JSESSIONID': 'D042C5FE4CFF337806D545B0001E7197'}
# Get SESSION
final_cookie = "JSESSIONID=" + result_cookie_dic["JSESSIONID"]  # SJSESSIONID=D042C5FE4CFF337806D545B0001E7197
print(final_cookie)

PUT request mode

# V tribe_ Edit column

# Please refer to the following for details of how to define the request header and automatically obtain cookie s
headers = {"Cookie": "VBlog(self.requests).get_cookie()"}
new_now_time = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
new_category_name = "Update column" + new_now_time
payload = {"id": 2010, "cateName": new_category_name}
self.requests.put("http://[server ip]:8081/admin/category/", headers=headers, data=payload)

DELETE request mode

# Delete column
result = self.requests.delete("http://[server ip]:8081/admin/category / "+" 2010 ", headers=headers)
print(result.json())  # {'status':' success', 'MSG': 'deletion succeeded!'}
self.assertEqual("Delete succeeded!", result.json()["msg"])

(4) cookie handling in interface automation testing

Manually pass in the value of the cookie (capture the packet through the browser F12 each time, and then copy the cookie in the request header)

import requests

# V tribe query column
url_v_category = "http://[server ip]:8081/admin/category/all“
# Custom request header
# If you want to add an HTTP header to the request, simply pass a dictionary to the headers parameter
v_headers = {
    "cookie": "studentUserName=ctt01; Hm_lvt_cd8218cd51f800ed2b73e5751cb3f4f9=1609742724,1609762306,1609841170,1609860946; adminUserName=admin; JSESSIONID=9D1FF19F333C5E25DBA60769E9F5248E"}
result = requests.get(url_v_category, headers=v_headers)
# Print the response result in json format
print(result.json())

Automatic cookie acquisition

import requests

url_v_login = "http://[server ip]:8081/login“
# Define parameters, dictionary format
payload = {'username': 'sang', 'password': '123'}
# Content-Type: application/json --> json
# Content-Type: application/x-www-form-urlencoded --> data
result = requests.post(url_v_login, data=payload)
# Convert the returned result to json format
result_json = result.json()
print(result_json)  # {'status':' success', 'MSG': 'login succeeded'}
# Get requestscookeiejar
result_cookie = result.cookies
print(result_cookie, type(result_cookie))  # RequestsCookieJar
# Convert requestscookeiejar to dictionary format
result_cookie_dic = requests.utils.dict_from_cookiejar(result_cookie)
print(result_cookie_dic)  # {'JSESSIONID': 'D042C5FE4CFF337806D545B0001E7197'}
# Get SESSION
final_cookie = "JSESSIONID=" + result_cookie_dic["JSESSIONID"]  # SJSESSIONID=D042C5FE4CFF337806D545B0001E7197
print(final_cookie)

Batch fetch cookie script

import requests


def get_cookie(username, password):
    """Students log in through the examination system to obtain a single cookie"""

    url_login = "http://[server ip]:8088/api/user/login“
    payload = {"userName": username, "password": password, "remember": False}
    result = requests.post(url_login, json=payload)
    # result_json = result.json()
    # print(result_json)

    # Get requestscookeiejar
    result_cookie = result.cookies
    # print(result_cookie, type(result_cookie))  # RequestsCookieJar
    # Convert requestscookeiejar to dictionary format
    result_cookie_dic = requests.utils.dict_from_cookiejar(result_cookie)
    # print(result_cookie_dic)  # {'SESSION': 'YzFkM2IzN2QtZWY1OC00Nzc4LTgyOWYtNjg5OGRiZDZlM2E4'}

    # Get SESSION
    final_cookie = "SESSION=" + result_cookie_dic["SESSION"]  # SESSION=Mzc2...
    return final_cookie
from test01.demo04_student_login import get_cookie
import os


def get_batch_cookies():
    """Batch acquisition cookie"""
    # Empty the contents of the cookie.csv file before obtaining the cookie
    # with open(r"D:\Desktop\Testman_Study\API_auto\file\cookies.csv", "w") as cookies_info:
    #     cookies_info.write("")
    # Or delete the file
    os.remove(r"D:\Desktop\Testman_Study\API_auto\file\cookies.csv")

    # Read csv file
    with open(r"D:\Desktop\Testman_Study\API_auto\file\register.csv", "r") as user_info:
        for user in user_info:
            user_list = user.strip().split(",")
            # Call the method to obtain a single cookie and pass in the registered user name and password
            cookies = get_cookie(user_list[0], user_list[1])
            # Append cookie to file
            with open(r"D:\Desktop\Testman_Study\API_auto\file\cookies.csv", "a") as cookies_info:
                cookies_info.write(cookies + "\n")


# Call method
get_batch_cookies()
register.csv(The premise is that these accounts and passwords have been registered and can be logged in directly)

poopoo001,123456,1
poopoo002,123457,2
poopoo003,123458,3
poopoo004,123459,4
......
cookies.csv

SESSION=ZmE3YmU4ZDctNDExZS00MDdhLWE0YjEtMjAyZjQxOTMxYmUx
SESSION=YjdkNTZhNTUtNGFmMi00MjVkLWEyNjctOTNiMmRmOTY1YTdm
SESSION=ZTJmMTYzMWEtZjUzOS00NTlhLWI0OWQtMzBmN2RkYmU4YmRi
SESSION=YTM0ZGRhOTctZjk5Ni00OWZhLTg1YTItZjUyMTMwZGE2MjVi
......

(5) Processing of different types of request parameters

import requests

# Article list
url_v_article = "http://[server ip]:8081/article/all“
v_headers = {
    "Cookie": "studentUserName=ctt01; Hm_lvt_cd8218cd51f800ed2b73e5751cb3f4f9=1609742724,1609762306,1609841170,1609860946; adminUserName=admin; JSESSIONID=9D1FF19F333C5E25DBA60769E9F5248E"}

# Customize the url parameters, define a dictionary, split the parameters, and then pass the dictionary to the params variable
article_params = {"state": 1,  # -1: All articles 1: Published 0: recycle bin 2: draft box
                  "page": 1,  # Show page 1
                  "count": 6,  # 6 per page
                  "keywords": ""  # Keywords included
                  }
keywords = ["Big orange cat", "Running man", "tooth"]
for keyword in keywords:
    article_params["keywords"] = keyword
    # headers and params are of indefinite length and pass parameters according to the defined dictionary
    result = requests.get(url_v_article, headers=v_headers, params=article_params)
    print(result.json())

(6) Combined with Python+Requests+Unittest framework for interface automation test

unittest framework:

if name == 'main':

if name == 'main' means:

  • When the. py file is run directly, the code block under if name == 'main' will be run;
  • When the. py file is imported as a module, the code block under if name == 'main' is not run.

(7) Advanced assertions in interface automation testing

Closed loop assertion (add -- > query -- > Modify -- > query -- > delete -- > query)

    def test_article(self):
        # ① V tribe_ New article
        now_time = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
        title = "Cai Tuotuo" + now_time
        payload = {"id": -1, "title": title, "mdContent": "Article content", "state": 1, "htmlContent": "<p>Article content</p>",
                   "dynamicTags": "", "cid": 62}
        headers = {"Cookie": VBlog(self.requests).get_cookie()}
        result = self.requests.post("http://[server ip]:8081/article/", headers=headers, data=payload)
        # ② Query article
        url_v_article = "http://[server ip]:8081/article/all“
        article_params = {"state": 1,  # -1: All articles 1: Published 0: recycle bin 2: draft box
                          "page": 1,  # Show page 1
                          "count": 6,  # 6 per page
                          "keywords": title  # Included keyword title
                          }
        result = requests.get(url_v_article, headers=headers, params=article_params, timeout=30)
        print(result.json())  # The response results are printed out in json
        ls = result.json()["articles"]
        act = 123
        # If the new article is found, it indicates that the new article is successful
        for l in range(0, len(ls)):
            if ls[l]["title"] == title:
                act = "ok"
                article_id = ls[l]["id"]
        self.assertEqual("ok", act)
        # ③ Edit article
        now_time = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
        title = "Modify article" + now_time
        payload = {"id": article_id, "title": title, "mdContent": "Modification content", "state": 1, "htmlContent": "<p>Modification content</p>",
                   "dynamicTags": "", "cid": 62}
        headers = {"Cookie": VBlog(self.requests).get_cookie()}
        self.requests.post("http://[server ip]:8081/article/", headers=headers, data=payload)
        # After editing, query the article
        url_v_article = "http://[server ip]:8081/article/all“
        article_params = {"state": 1,  # -1: All articles 1: Published 0: recycle bin 2: draft box
                          "page": 1,  # Show page 1
                          "count": 6,  # 6 per page
                          "keywords": title  # Included keyword title
                          }
        result = requests.get(url_v_article, headers=headers, params=article_params, timeout=30)
        print(result.json())  # The response results are printed out in json
        ls = result.json()["articles"]
        act = 123
        # If the revised article is found, it indicates that the editing is successful
        for l in range(0, len(ls)):
            if ls[l]["title"] == title:
                act = "ok"
                article_id = ls[l]["id"]
        self.assertEqual("ok", act)
        # ④ View Article Details
        article_id = str(article_id)
        result = self.requests.get("http://[server IP]: 8081 / article / "+ article_id, headers = headers)
        print(result.json())
        if result.json()["title"] == title:
            act = "ok"
        self.assertEqual(act, "ok")
        # ⑤ Delete article
        payload = {'aids': article_id, 'state': 1}
        result = self.requests.put("http://[server ip]:8081/article/dustbin", headers=headers, data=payload)
        print(result.json())
        act = result.json()["msg"]
        self.assertEqual(act, "Delete succeeded!")

(8) Generate visual HTML test report through HTMLTestRunner.py

HTMLTestRunner.py Baidu online disk link:

from reports import HTMLTestRunner
from case.exam_case.teacher_case import TeacherCase
import unittest
import os
import time

# Create test suite
suite = unittest.TestSuite()

# Add test cases and execute them according to the addition order
# Add a single test case
# suite.addTest(TeacherCase("test_001_admin_login"))

# Add multiple test cases
suite.addTests([TeacherCase("test_001_admin_login"),
                TeacherCase("test_002_insert_paper"),
                TeacherCase("test_003_select_paper"),
                ])

# Define the storage path of the test report
path = r"D:\Desktop\Testman_Study\unittest_exam_system\reports"
# Determine whether the path exists
if not os.path.exists(path):
    # If not, create one
    os.makedirs(path)
else:
    pass
# Define a timestamp for test report naming
now_time = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(time.time()))
reports_path = path + "\\" + now_time + "(exam_report).html"
reports_title = u"Examination system&V Tribe - Test Report"
desc = u"Examination system&V Interface automation test report"
# Binary write
fp = open(reports_path, "wb")
runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title=reports_title, description=desc)
# function
runner.run(suite)
postman,JMeter,requests Summary:
  • postman: interface function test
  • JMeter: interface performance test
  • requests: interface automation
  • 🐵 Common features of the three: they can complete interface function test.

Finally, it can be in the official account: the sad spicy bar! Get a 216 page interview document of Software Test Engineer for free. And the corresponding video learning tutorials for free!, It includes basic knowledge, Linux essentials, Shell, Internet program principles, Mysql database, special topics of packet capture tools, interface test tools, test advanced Python programming, Web automation test, APP automation test, interface automation test, advanced continuous test integration, test architecture, development test framework, performance test, security test, etc.

If my blog is helpful to you and you like my blog content, please click "like", "comment" and "collect" for three times! Friends who like software testing can join our testing technology exchange group: 914172719 (there are various software testing resources and technical discussions)

Haowen recommendation

Job transfer interview, job hopping interview, these interview skills that software testers must know!

Interview experience: move bricks in first tier cities! Another software testing post, 5000 will be satisfied

Interviewer: I've worked for three years and have a preliminary test? I'm afraid your title of software test engineer should be enclosed in double quotation marks

What kind of person is suitable for software testing?

The man who left work on time was promoted before me

The test post changed jobs repeatedly and disappeared

Keywords: Python Programmer unit testing software testing IT

Added by mikeatrpi on Wed, 29 Sep 2021 23:25:54 +0300