项目框架搭建

1.自动化测试流程

  • 需求分析。需求文档,接口文档。抓包接口
  • 计划。进度?是否自动化?优先级?
  • 测试用例(是从手工测试提取出来的)
  • 评审
  • 执行,(写代码)
  • 报告

接到一个项目,在需求分析的阶段,我们需要熟悉的部分包含:

  • 需求文档,功能展示以及交互
  • 接口文档,后端数据是怎么传输
  • 数据库账号,数据库地址,结构帮大家熟悉整个项目的轮廓,表字段
  • 测试环境/环境怎么搭建
  • 原型图

测试计划一般由项目经理制定,主要是时间、技术、进度、优先级的管控,可以确认哪些功能需要引入自动化测试(自动化测试技术python/java)。

测试计划还会涉及到可行性分析,风险分析。

测试用例的编写一般是在excel文档中实现的。

通常来说,任何的一个项目或者是新功能,会先进行手工测试,也是要进行全量的用例编写。

自动化测试主要应用场景:

  • 冒烟测试:确认主流程是否能正常运行。
  • 回归测试:验证问题并检查是否引起其他问题的测试
  • 持续集成:一天可能要做好几次的测试,反复测试

2.接口需求分析

接口文档形式:

  • 纸质文档(电子)
  • open api,以前叫做swagger,在网站上进行访问
  • 什么都没有,全凭一张嘴(自己抓包)

通过抓包,postman调试工具 ,我们知道了怎么设计用例,预期结果。

3.用例设计

excel编写,以前程贷注册接口为例。

注意:json数据一定要符合规范,不然转成字典会报错。(引号必须是双引号)

预期结果根据postman运行后得出。

项目框架搭建_第1张图片

4.编写自动化测试用例函数

如果领导给你一个自动化测试的计划,

先不要着急做到十全十美,第一步是验证你的自动化测试程序是否能正常运行。

先把功能实现。

写一个单独的自动化测试用例函数。test_开头的测试用例函数,需要有请求发送,得到响应结果,断言。然后生成测试报告。

test_register.py内容如下:

import unittest
import requests


class TestRegister(unittest.TestCase):

    def test_register_1(self):
        #  1.准备测试数据
        url = 'http://api.lemonban.com:8766/futureloan/member/register'
        method = 'post'
        headers = {"X-Lemonban-Media-Type": "lemonban.v2"}
        json_data = {"mobile_phone": "", "pwd": "12345678"}
        expected = {
            "code": 1,
            "msg": "手机号为空",
            "data": None,
            "copyright": "Copyright 柠檬班 © 2017-2020 湖南省零檬信息技术有限公司 All Rights Reserved"
        }
        # 2.发送接口请求,得到实际结果
        resp = requests.request(method=method, url=url, headers=headers, json=json_data)
        actual = resp.json()
        # 3.预期结果个实际结果的断言
        self.assertEqual(expected, actual)

run.py用于生成测试报告:

import unittest
import unittestreport

# 收集用例,tests用例所在的包
suite = unittest.defaultTestLoader.discover('tests')
# 运行用例
# runner = unittest.TextTestRunner()
# runner.run(suite)
# 生成测试报告
runner = unittestreport.TestRunner(suite, tester='困困')
runner.run()

运行结果:

项目框架搭建_第2张图片

有了以上的基础后,我们可以引入ddt,优化下测试用例函数,降低代码重复率。

ddt适用的场景:不同的数据,测试步骤是一样的。

test_register_ddt.py:

import unittest
import requests
import json
from common.excel import read_excel
from common.logger import my_log
from ddt import ddt, data
from setting.config import config_file, host

# 得到测试数据
excel_data = read_excel(file=config_file, sheet_name='register')


@ddt
class TestLogin(unittest.TestCase):

    @data(*excel_data)
    def test_login(self, info):
        # TODO:域名和端口,环境和变化的是否更方便的修改,不需要放在excel中,可以放在配置文件config.py
        my_log.info(f'测试用例{info}正在执行。。。')
        url = host + info['url']
        method = info['method']
        # 反序列化,将json格式字符串转化成python字典,因为requests.request的参数需要字典格式
        json_data = json.loads(info['json'])
        headers = json.loads(info['headers'])
        expected = json.loads(info['expected'])
        resp = requests.request(method=method, url=url, headers=headers, json=json_data)
        actual = resp.json()
        self.assertEqual(expected, actual)

5.分层思想

tests/:存储自动化用例

common/:通用模块

logs/:保存日志文件

data/:保存测试数据,excel文件

setting/:配置文件

reports/:保存测试报告

run.py:收集用例,运行用例,生成测试报告

项目框架搭建_第3张图片

6.框架优化

目前整个框架已经实现了流程的正常运行,但还有几个问题需要优化下。

6.1 生成测试报告,每次都是生成report.html,每次生成都会覆盖,那有没有办法每次都生成新的报告,不覆盖呢?解决方式报告名称添加时间戳。

import unittest
import unittestreport
from datetime import datetime

# 收集用例,tests用例所在的包
suite = unittest.defaultTestLoader.discover('tests')
# 生成测试报告
# 获取时间戳,now()获取现在的时间,strftime()转化成字符串
report_time = datetime.now().strftime("%Y%m%d%H%M%S")
# 字符串拼接
filename = f'report-{report_time}.html'
runner = unittestreport.TestRunner(suite, tester='困困', filename=filename)
runner.run()

运行结果:

项目框架搭建_第4张图片 

6.2 手机号注册成功后,如果再次运行用例,该条用例一定会失败,那怎么避免手机号码重复的问题呢?

方案1:手工+1,可能与其他人已注册的号码冲突,也可能运营商不支持此号码段。

方案2:数据库清掉。不建议删数据,然后也不一定有删除的权限。

方案3:参数动态化,手机号随机生成,excel中使用标记(注册成功的用例记录)。

手机号随机生成,可以使用第三方库faker实现,使用前先安装:pip install faker

项目框架搭建_第5张图片

伪造手机号函数存放在common文件夹下,

helper.py:

from faker import Faker


def generate_mobile():
    faker = Faker(locale=['zh-cn'])
    # 生成伪造手机号码
    return faker.phone_number()

 test_register_ddt.py:

import unittest
import requests
import json
from common.excel import read_excel
from common.logger import my_log
from common.helper import generate_mobile
from ddt import ddt, data
from setting.config import config_file, host


# 得到测试数据
excel_data = read_excel(file=config_file, sheet_name='register')


@ddt
class TestLogin(unittest.TestCase):

    @data(*excel_data)
    def test_login(self, info):
        # TODO:域名和端口,环境和变化的是否更方便的修改,不需要放在excel中,可以放在配置文件config.py
        my_log.info(f'测试用例{info}正在执行。。。')
        url = host + info['url']
        method = info['method']
        # 反序列化,将json格式字符串转化成python字典,因为requests.request的参数需要字典格式
        json_data = info['json']
        # 检测:如果json_data中存在某个标记,就说明需要自动生成一个手机号码
        # 直接调用函数generate_mobile
        # json_data = 替换完成新的手机号之后的字符串
        if '#mobile_phone#' in json_data:
            mobile = generate_mobile()
            json_data = json_data.replace('#mobile_phone#',mobile)
        json_data = json.loads(json_data)
        headers = json.loads(info['headers'])
        expected = json.loads(info['expected'])
        resp = requests.request(method=method, url=url, headers=headers, json=json_data)
        actual = resp.json()
        self.assertEqual(expected, actual)

运行结果:

项目框架搭建_第6张图片

从运行结果中可以看出来,虽然手机号实现动态获取且随机了,但运行用例还是失败了,因为预期结果和实际结果中有些字段的值是动态的且没有必要进行比较的,比如data,copyright。

6.3 全量断言和部分断言

-全量断言:一个字都不能差,麻烦

-部分断言,提取有用的关键字段进行断言,code,msg。实战当中基本使用部分断言。

修改excel中expected的值:

项目框架搭建_第7张图片

修改代码:

        # 简单版本 部分断言
        self.assertEqual(expected['msg'], actual['msg'])
        # 多个字段需要校验,对expected进行for循环
        for key, value in expected.items():
            self.assertEqual(value, actual[key])
        # 笨方法,多个字段分别断言
        self.assertEqual(expected['msg'], actual['msg'])
        self.assertEqual(expected['code'], actual['code'])

  test_register_ddt.py:

import unittest
import requests
import json
from common.excel import read_excel
from common.logger import my_log
from common.helper import generate_mobile
from ddt import ddt, data
from setting.config import config_file, host

# 得到测试数据
excel_data = read_excel(file=config_file, sheet_name='register')


@ddt
class TestLogin(unittest.TestCase):

    @data(*excel_data)
    def test_login(self, info):
        # TODO:域名和端口,环境和变化的是否更方便的修改,不需要放在excel中,可以放在配置文件config.py
        my_log.info(f'测试用例{info}正在执行。。。')
        url = host + info['url']
        method = info['method']
        # 反序列化,将json格式字符串转化成python字典,因为requests.request的参数需要字典格式
        json_data = info['json']
        # 检测:如果json_data中存在某个标记,就说明需要自动生成一个手机号码
        # 直接调用函数generate_mobile
        # json_data = 替换完成新的手机号之后的字符串
        if '#mobile_phone#' in json_data:
            mobile = generate_mobile()
            json_data = json_data.replace('#mobile_phone#', mobile)
        json_data = json.loads(json_data)
        headers = json.loads(info['headers'])
        expected = json.loads(info['expected'])
        resp = requests.request(method=method, url=url, headers=headers, json=json_data)
        actual = resp.json()
        # 简单版本 部分断言
        # self.assertEqual(expected['msg'], actual['msg'])
        # 多个字段需要校验,对expected进行for循环
        for key, value in expected.items():
            self.assertEqual(value, actual[key])
        # 笨方法,多个字段分别断言
        # self.assertEqual(expected['msg'], actual['msg'])
        # self.assertEqual(expected['code'], actual['code'])

运行结果:

项目框架搭建_第8张图片

7.扩展

7.1测试金字塔

项目框架搭建_第9张图片

从下往上:单元测试->服务(接口)测试->UI用户界面测试->系统测试(手工测试)

左侧代表:速度

右侧代表:成本

7.2 什么样的项目适合做自动化测试

  • 需求稳定,不会频繁变更。(项目初期不太适合)
  • 研发和测试周期长,需要频繁执行回归测试。
  • 需要再多种平台上重复运行相同测试的场景。
  • 某些测试项目通过手工测试无法实现,或者手工测试成本高。
  • 被测软件的开发较为规范,能够保证系统的可测试性。

7.3 图片验证码

测试接口时,遇到图片验证码的问题,该怎么解决?

  • 找开发直接关掉验证码的功能
  • 找开发万能验证码
  • 对接第三方平台(超级鹰)
  • 代码的方式去实现验证码的操作对我们来说比较困难(OCR,图像识别,图像处理,机器学习(AI))

7.4 第三方伪造库:faker

from faker import Faker

# zh-cn指定中国地区
faker = Faker(locale=['zh-cn'])
# 生成伪造手机号码
print(faker.phone_number())
# 伪造电商地址
print(faker.address())
# 伪造公司
print(faker.company())
# 伪造姓名
print(faker.name())
# 伪造身份证号
print(faker.ssn())

运行结果:

项目框架搭建_第10张图片

7.5 debug

在编写代码过程中,调试很重要:

首先程序报错:

  • 从报错信息中查看error message
  • 找到报错行,报错信息中哪个文件是你写的,行号,跳到行号
  • 如果有多个文件是自己编写的,行号都找出来
  • 哪一行出错,就在哪一行设置断点。通过debug运行。

你可能感兴趣的:(笔记,Python,python)