DDT data-driven testing for python interface automation

foreword

Today I want to talk to you about how DDT data drives testing in python interface automation , so I won’t talk nonsense and go directly to the topic.

 

1. Brief introduction

DDT (Date Driver Test), the so-called data-driven test, simply means that the execution of the automated test is driven by the change of the data, and finally causes the change of the test result. By using the data-driven test method, in the test scenario where multiple sets of data need to be verified, external data sources can be used to parameterize the input, output and expected values, avoiding the use of hard-coded data in the test, that is, test data and use case scripts Code separation.

​ DDT is actually a decorator, it will determine how many test cases to generate based on the data you pass in.
 

Second, the meaning of use

1. High code reuse rate: a test logic only needs to be written once, multiple test data can be reused, and the efficiency of writing test scripts can be improved at the same time.

2. High efficiency in abnormal troubleshooting: According to the test data, each piece of data generates a test case, and the test cases are separated from each other. If one fails, it will not affect other test cases.

3. High maintainability of the code: The concise and clear test framework is conducive to other colleagues to read and improve the maintainability of the code.
 

3. Installation and import

​ cmd command line to execute the installation: pip install ddt

Import directly into the module: import ddt, or import specific decorators: from ddt import ddt, data, unpack

4. Detailed explanation of the use of ddt

Three main points:

  • @ddt: decorate the test class
  • @data: decorate the test case
  • @unpack: decorate test cases

The prerequisite for using ddt is to have a test case class, then use @ddt to decorate the test case class, and use @data (test data) to decorate the test case, as shown in the following login interface example:

from ddt import ddt, data
from common.read_excel import ReadExcel
from common.my_logger import log
 
 
@ddt  # 装饰登录测试用例类,声明使用ddt
class LoginTestCase(unittest.TestCase):
    
    excel = ReadExcel("cases.xlsx", "login")
    cases = excel.read_data()
    
    @data(*cases)	# 装饰测试用例
    def test_login(self, case):
        case_data = eval(case["data"])
        expected = eval(case["expected"])
        case_id = case["case_id"]
        result = login_check(*case_data)
        response = self.http.send(url=url, method=method, json=data, headers=headers)
        result = response.json()
        try:
            self.assertEqual(expected["code"], result["code"])
            self.assertEqual((expected["msg"]), result["msg"])
        except AssertionError as e:
            log.info("用例:{}--->执行未通过".format(case["title"]))
            print("预期结果:{}".format(expected))
            print("实际结果:{}".format(result))
            raise e
        else:
            log.info("用例:{}--->执行通过".format(case["title"]))
 
 
if __name__ == '__main__':
    unittest.main()

@ddt What it does is actually equivalent to this code: LoginTestCase = ddt(LoginTestCase), pass the specific class name to ddt, and tell ddt that this test case class should be driven by data.

What @data does is to pass the test data as a parameter to the test case. One data corresponds to generate a test case. If there are multiple data in the data, then multiple test cases are generated correspondingly. If there are sequence types of data such as tuples, lists, etc. in data, data will treat them as a whole, that is, a test data.

​ If you want to pass multiple parameters to a test case at a time, you need to decompose the data in the script or use @unpack to decompose the data. The test case in the above example only uses one parameter, but this parameter case is a dictionary, which already contains multiple data, and you can directly use the key to obtain the corresponding value. @unpack can split the data of the sequence type into multiple, and pass multiple parameters to the test case, but the test case also needs to define the same number of parameters to receive.

The source of the test data cases in the above example is to use openpyxl to read the test data in excel. Here it is directly explained that the cases are actually a list like the following:

cases = [{'case_id': 1, 'title': '正常登录', 'data': '("test", "Test1234")', 'expected': '{"code": 0, "msg": "登录成功"}'}, {'case_id': 2, 'title': '密码错误', 'data': '("test", "123")', 'expected': '{"code": 1, "msg": "账号或密码不正确"}'}, {'case_id': 3, 'title': '账户名错误', 'data': '("test11", "Test1234")', 'expected': '{"code": 1, "msg": "账号或密码不正确"}'}]
 
# *解包后,一个字典就是一个测试用例数据
# 如第一个字典:{'case_id': 1, 'title': '正常登录', 'data': '("test", "Test1234")', 'expected': '{"code": 0, "msg": "登录成功"}'}

​ Through * unpacking, its data is 3 dictionaries, each time a dictionary is passed to the test case, and this dictionary stores a complete test data of the login interface test case, including the use case id, use case title, The account password for the test and the result expected to be returned.

summary:

  • @data(a,b): a and b each run a use case
  • @data(*(a,b): a and b each run a use case, use * to unpack, equivalent to @data(a,b)
  • @data([a,d],[c,d]) If there is no @unpack[a,b], [c,d] will be passed as a parameter into the use case, that is, run once with [a,b], use [c,d] runs once; if there is @unpack, [a,b] will be decomposed, and two parameters are passed to the use case at a time. The use case needs to define two parameters to receive @unpack applicable tuples, lists or dictionaries, But when a dictionary is passed in, the key of the dictionary and the parameter name defined by the use case need to be consistent
     

5. Expansion

Key code: @file_data, transfer file (json/yaml)

# 传递json
"""
json文件数据
{
	"token":123456,
	"actionName": "api.login",
	"content": {
		"user": "miki",
		"pwd": "Test123"
	}
}
"""
"""
yaml文件
test_list:
  - 11
  - 22
  - 12
sorted_list: [ 11, 12, 22 ]
"""
from ddt import *
 
 
@ddt	# 声明使用ddt
class TestFile(unittest.TestCase):
 
    @file_data('D:/test/test.json')
    def test_json(self, json_data):
        print(json_data)
        
    @file_data('D:/test/test.yaml')
    def test_yaml(self, yaml_data):
        print("yaml", yaml_data)

Summarize

That's all for today's article, I hope it can help everyone, friends who like it can like it, collect comments and pay attention, the author will post some benefits and small surprises at the back of the article from time to time, if you like it, please remember to like it .

 

Guess you like

Origin blog.csdn.net/lzz718719/article/details/130728535