公共用例库计划--个人版(一)

1、公共用例库计划

1.1、目标

在公司测试管理体系的演变过程中,从禅道过渡到devops再到云效平台,我们已经实现了对bug和用例的有效集中管理。然而,在实际操作中发现,尽管用例管理得到了初步整合,但在面对不同系统和测试类型时,缺乏一套完善的公共用例库体系,导致每次进行新系统测试时都需要大量重复编写测试用例。即使在一定程度上参考了以往项目的用例,但复用程度并不理想,这不仅浪费了宝贵的测试资源,也不利于经验总结与传承。

因此,本次计划的核心任务是开发一个,个人版的公共用例库,旨在将各系统和各类测试场景下的通用、基础以及关键功能的测试用例进行系统性地归纳整理,并以提高用例的复用率为目标,力求最大限度地减少重复劳动,提升测试效率。通过搭建并维护这个公共用例库,能够更好地积累和分享测试经验,降低由于人为疏忽或遗漏而产生的漏测风险,确保产品质量得到持续稳定的保障。同时,这一举措也将有助于团队内部知识共享和标准化建设,为今后的测试工作打下坚实的基础。

1.2、任务概述

工作内容包括:完成公共用例库的开发实施工作,包括需求分析、系统设计、开发、测试、打包、运行维护等工作。

2、分析与设计

2.1、功能性需求

2.1.1 主页
  • 主页作为系统的入口和概览界面,主要展示关键的统计信息:
    • 模块总数:展示当前系统内所有模块的数量。
    • 用例总数:显示所有已创建的测试用例数量。
    • 各用例类型数:列出并统计各类测试用例(如功能测试、性能测试、兼容性测试等)的数量。
2.1.2 用例库
  • 模块管理
    • 模块新增:创建新的测试模块,用于归类和组织相关联的测试用例,支持3级目录。
    • 模块编辑:更改模块名称、描述或其他属性,以适应业务需求的变化。
    • 模块查询:搜索特定的测试模块,便于查看该模块下的所有测试用例。
    • 模块删除:将不再需要的模块移至回收站,保持用例库结构清晰有序。
  • 用例管理
    • 新增:先选择模块,再创建新的测试用例,填写详细的用例标题、前置条件、操作步骤、预期结果等信息。
    • 编辑:提供对已有用例进行修改的功能,可以更新用例的各种属性或内容。
    • 复制:支持复制现有用例在原模块下创建一个相同的新用例,便于快速生成类似的测试场景。
    • 查询:通过关键字搜索、过滤器等方式查找所需的测试用例。
    • 删除:从用例库中移除不再需要的测试用例,放入回收站而非直接永久删除。
2.1.3 导入导出
  • 下载模版:为用户提供标准的Excel模版文件,方便按照统一格式编写和导入用例数据。
  • 导入用例Excel:支持用户上传已经填写好的Excel模版文件,自动解析并导入到用例库中。
  • 导出用例:选择特定的模块,将该模块下的所有用例数据导出为Excel文件。
2.1.4 回收站
  • 恢复:对于被删除的用例或模块,允许用户在一定时间内将其恢复到原始位置。
  • 彻底删除:若确定不再需要某项已放入回收站的内容,可执行彻底删除操作,使其无法再被恢复。
2.1.5 关于
  • 提供系统版本信息、版权声明、使用帮助文档等相关信息,帮助用户更好地理解和使用公共用例库系统。

在这里插入图片描述

2.3、环境准备

开发流程:使用Qt Disinger设计UI,PyUIC把Qt Designer生成的.ui文件换成.py文件
环境:

win10+pycharm
Python3.9
	sqlite3
	PyQt6		6.6.1
	PyQt6-Qt6	6.6.1
	PyQt6-sip	13.6.0
	pyqt6-tools	6.4.2.3.3
Qt Designer软件	5.11.1

环境配置参考:

  • Python GUI编程:https://www.kancloud.cn/ay66544/pygui/3044831
  • PyQt窗口设计之Qt
    Designer:https://blog.csdn.net/Itsme_MrJJ/article/details/122668802

环境安装pyqt下载一直很慢,国内源也是。PyQt6与PyQt6-Qt6必须安装版本一致,不然会报错dll找不到运行程序。

3、数据架构设计

使用SQLite数据库存储用例及模块数据,SQLite 的使用下面这篇文章讲的很好。后面的封装示例直接拿来用了。
Python操作SQLite数据库(非常详细):https://c.biancheng.net/view/vb3b93m.html

3.1、表设计

表一:testcase(测试用例表)
表二:module(模块表)
在这里插入图片描述

3.2、数据库表与操作封装

至此,数据库层面的代码基本实现,后续需要设计GUI界面,与功能需求的代码实现

# !/usr/bin/env python
# -*- coding:utf-8 -*-

import sqlite3
import datetime

class casedb:
    '''用例库操作,增删改查'''

    def __init__(self):
        '''初始化,连接数据库,建表'''
        try:
            self.connect()
            # 创建模块表
            self.cursor.execute(f"""
                CREATE TABLE IF NOT EXISTS  module (
                    moduleid INTEGER PRIMARY KEY AUTOINCREMENT,--模块编号
                    parent_id TEXT NOT NULL,--父id
                    level TEXT,--层级
                    parent_path TEXT,--路径
                    modulename TEXT NOT NULL,--名称
                    status TEXT,--是否启用 1/0
                    order_num TEXT--顺序
                )""")
            # 创建用例表
            self.cursor.execute("""  
                CREATE TABLE IF NOT EXISTS testcase (  
                    caseid INTEGER PRIMARY KEY AUTOINCREMENT,  --用例编号
                    moduleid INTEGER NOT NULL,  --所属模块
                    title TEXT NOT NULL,  --用例标题
                    preconditions TEXT,  --前置条件
                    step TEXT NOT NULL,  --步骤
                    expect TEXT,  --预期
                    keyword TEXT,  --关键词
                    priority TEXT,  --优先级
                    types TEXT,  --用例类型
                    status TEXT,  --用例状态
                    modificationdate TEXT default TIMESTAMP,  --修改日期
                    counts TEXT,  --导出次数
                    remarks TEXT  --备注
                )""")
            self.conn.commit()
            self.over()
            print("[数据库连接成功]")

        except Exception as e:
            print("[create table error]", e)


    def connect(self):
        '''连接数据库'''
        self.conn=sqlite3.connect('testcaes.db')  # 连接数据库
        self.cursor=self.conn.cursor()  # 创建游标


    # 插入或更新表数据,一次插入或更新一条数据
    def operate_one(self, sql: str, value: tuple):
        """
        插入或更新单条表记录
        :param sql: insert语句或update语句
        :param value: 插入或更新的值,形如()
        :return: True表示插入或更新成功
        """
        try:
            self.cursor.execute(sql, value)
            self.conn.commit()
            if 'INSERT' in sql.upper():
                print("[insert one record success]")
            if 'UPDATE' in sql.upper():
                print("[update one record success]")
            return True
        except Exception as e:
            print("[insert/update one record error]", e)
            self.conn.rollback()
            return False


        # 插入或更新表数据,一次插入或更新多条数据
    def operate_many(self, sql: str, value: list):
        """
        插入或更新多条表记录
        :param sql: insert语句或update语句
        :param value: 插入或更新的字段的具体值,列表形式为list:[(),()]
        :return: True表示插入或更新成功
        """
        try:
            # 调用executemany()方法
            self.cursor.executemany(sql, value)
            self.conn.commit()
            if 'INSERT' in sql.upper():
                print("[insert many  records success]")
            if 'UPDATE' in sql.upper():
                print("[update many  records success]")
            return True
        except Exception as e:
            print("[insert/update many  records error]", e)
            self.conn.rollback()
            return False

        # 查询一条数据
    def query_one(self, sql: str, params=None):
        """
        查询单条数据
        :param sql: select语句
        :param params: 查询参数,形如()
        :return: 语句查询单条结果
        """
        try:
            if params:
                self.cursor.execute(sql, params)
            else:
                self.cursor.execute(sql)
            # 调用fetchone()方法
            r=self.cursor.fetchone()
            print("[select one record success]")
            return r
        except Exception as e:
            print("[select one record error]", e)

    # 查询多条数据
    def query_many(self, sql: str, params=None):
        """
        查询多条数据
        :param sql: select语句
        :param params: 查询参数,形如()
        :return: 语句查询多条结果
        """
        try:
            if params:
                self.cursor.execute(sql, params)
            else:
                self.cursor.execute(sql)
            # 调用fetchall()方法
            r=self.cursor.fetchall()
            print(f"[select many records success]")
            return r
        except Exception as e:
            print("[select many records error]", e)

    # 删除表数据
    def delete_record(self, sql: str):
        """
        删除表记录
        :param sql: 删除记录SQL语句
        :return: True表示删除成功
        """
        try:
            if 'DELETE' in sql.upper():
                self.cursor.execute(sql)
                self.conn.commit()
                print("[detele record success]")
                return True
            else:
                print("[sql is not delete]")
                return False
        except Exception as e:
            print("[detele record error]", e)
            return False

    def over(self):
        '''关闭连接'''
        self.cursor.close()
        self.conn.close()


    def main(self):

        #插入数据
        self.operate_one(('INSERT INTO module VALUES (NULL,?,?,?,?,?,?)'),('1','1','0/1','更多查询','1','1'))
        # self.operate_many(('INSERT INTO testcase VALUES (NULL,?,?,?,?,?,?,?,?,?,?,?,?,?)'),[
        #                  ('1', '选择查询日期', '无', '1、打开页面,选择日期,点击查询', '查询出相应日期结果', '日期查询', '', '', '', '', '', '', ''),
        #                     ('1', '选择下拉', '无', '1、打开页面,选择下拉,点击查询', '查询出相应结果', '下拉查询', '', '', '', '', '', '', '')])

        # 更新数据SQL语句
        current_time=datetime.datetime.now()# 获取当前时间
        update_sql="update testcase set modificationdate=? where caseid=?"
        update_value=(current_time, '2')
        update_values=[(current_time, '1'), (current_time, '3')]
        self.operate_one(update_sql, update_value)# 一次更新一条数据
        self.operate_many(update_sql, update_values)# 一次更新多条数据

        #查询数据
        row=self.query_many(("select * from testcase where moduleid=?"),'1')
        print(row)

        #删除数据
        delete_sql="delete from module where moduleid = '7'"
        self.delete_record(delete_sql)
        self.over()


if __name__ == '__main__':

    a=casedb()
    a.connect()
    row=a.query_many(("select * from module"))
    print(row)
    a.over()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/281938.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

详解信道容量,信道速率,安全速率的区别

目录 一. 信道容量与信道速率 二. 小结 三. 安全速率与物理层安全 3.1 香农物理层安全模型 3.2 安全信道速率 四. 补充安全中断概率(Secrecy Outage Probability, SOP) 五. 补充安全分集度(Secrecy Diversity Order, SDO) …

【深度学习】Normalizing flow原理推导+Pytorch实现

1、前言 N o r m a l i z i n g f l o w \boxed{Normalizing \hspace{0.1cm} flow} Normalizingflow​,流模型,一种能够与目前流行的生成模型—— G A N 、 V A E \boxed{\mathbf{GAN、VAE}} GAN、VAE​相媲美的模型。其也是一个生成模型,可是…

【网络安全 | Misc】Ditf 安恒九月赛

正文 binwalk发现rar: 修改后缀,打开需要密码: 修改高度: 得到密码: StRe1izia得到一个流量包: 联系上文搜素png得到: 追踪流: 得到Base64代码: flag{Oz_4nd_Hir0_lov3_F…

算法通关村第十四关—堆能高效解决的经典问题(白银)

堆能高效解决的经典问题 一、在数组中找第K大的元素 LeetCode215 给定整数数组ums和整数k,请返回数组中第k个最大的元素。请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素。 示例1: 输入:[3,2,1,5,6,4]和…

循环生成对抗网络(CycleGAN)

一、说明 循环生成对抗网络(CycleGAN)是一种训练深度卷积神经网络以执行图像到图像翻译任务的方法。网络使用不成对的数据集学习输入和输出图像之间的映射。 二、基本介绍 CycleGAN 是图像到图像的翻译模型,就像Pix2Pix一样。Pix2Pix模型面临…

计算机组成原理复习7

内存管理 文章目录 内存管理存储器概述存储器的分类按在计算机中的作用(层次)分类按存储介质分类按存取方式分类按信息的可保存性分类 存储器的性能指标存储容量单位成本存储速度:数据传输率数据的宽度/存储周期 存储器的层次化结构多级存储系…

抖音详情API:从零开始构建抖音应用

随着短视频的兴起,抖音已经成为了一个全球范围内的热门平台。对于开发人员而言,利用抖音详情API从零开始构建抖音应用具有巨大的潜力和机会。本文将为你提供从零开始构建抖音应用的指南,包括开发环境搭建、API请求格式、用户认证等关键环节&a…

八. 实战:CUDA-BEVFusion部署分析-环境搭建

目录 前言0. 简述1. CUDA-BEVFusion浅析2. CUDA-BEVFusion环境配置2.1 简述2.2 源码下载2.3 模型数据下载2.4 基础软件安装2.5 protobuf安装2.5.1 apt 方式安装2.5.2 源码方式安装 2.6 编译运行2.6.1 配置 environment.sh2.6.2 利用TensorRT构建模型2.6.3 编译运行程序 2.7 拓展…

【电子通识】LED有关的几个参数和定义

主波长与峰值波长 看LED灯数据手册的时候会发现有两种不同的波长参数:“峰值波长 Peak Wavelength”和 “主波长 Dominant Wavelength”,那么这两个波长代表什么? 峰值波长 λP(Peak Wavelength ) : 定义为光谱辐射功率最大处所对…

JavaScript元素根据父级元素宽高缩放

/*** 等比缩放* param wrap 外部容器* param container 待缩放的容器* returns {{width: number, height: number}}* 返回值:width:宽度, height:高度*/aspectRatio(wrap: any, container: any) {// w h / ratio, h w * ratioconst wrapW wrap.width;const wrapH…

2023年度总结——关于如何认清自己是个FW

前言 不到各位有没有今年过得特别快的感觉。写总结时候一整理,我敲,我今年这么忙? 从三月份开说 三月份 这段时间刚开学,还算比较懵懂。不过初生牛犊不怕虎,那个寒假学了点怎么挖edusrc,开学迫不及待地…

AI按理说应该最擅长理工,为啥先冲击文艺行业?

介绍 本人数据AI工程师,我的观点对全行业都有冲击,当AI大模型持续进化之时,没有一家公司能独善其身。 本文从产业架构上、论文体量、基础Pass能力、通用大模型、AI开源社区、业务属性大模型、内容消费工具、创作工具赛道、企业服务这些板块…

day12--java高级编程:网络通讯

5 Day19–网络通信(Socket通信) 说明: io流是跟本地的文件进行数据的传输,读或者写。网络通信:数据在网络中进行的传输。 本章专题与脉络 1. 网络编程概述 Java是 Internet 上的语言,它从语言级上提供了对网络应用程序的支持&…

常用的 MySQL 可视化客户端

数据库可视化客户端(GUI)让用户在和数据库进行交互时,能直观地查看、创建和修改对象,如:表、行和列。让数据库操作变得更方便了。 今天,我们来了解下目前市场上最常用的 MySQL 可视化客户端。 官方&#x…

Stata18软件安装包下载及安装教程

Stata 18下载链接:https://docs.qq.com/doc/DUm5pRlFJaWV5aWtY 1.选中下载好的安装包,右键选择解压到“Stata18”文件夹 2.选中“SetupStata18.exe”,右键以管理员身份运行 3.点击“Next” 4.选择“I accept.....”,选择“Next” 5.点击“Nex…

MySQL Too many connections报错

MySQL 时不时出现Too many connections报错,重启MySQL就好了 但是过段时间又出现 一、解决方案: 1.修改mysql最大连接数 set global max_connections500; 以上是修改立即生效的,重启MySQL就会还原回去 在MySQL配置文件修改 max_connection…

matalb实践(十二):减肥

1.题目 2.解答 2.1模型假设 1.体重增加正比于吸收的热量,平均每8000kcal增加体重1kg 2.身体正常代谢引起的体重减少正比于体重,每周每千克体重消耗热量一般在200kcal至320kcal之间,且因人而异,这相当于体重70kg的人每天消耗2000k…

【ECharts系列】ECharts 图表渲染问题解决方案

1 问题描述 echats 渲染,第一次的时候只出现Y轴数值,不出现X轴数值,切换下页面,X轴数值就能出现。 2 原因分析 如果在使用ECharts渲染时,X轴数值只在切换页面后才出现,可能是因为ECharts在初始化时没有正确…

计算机视觉:朗伯光度立体法(Lambertian Photometric Stereo)

计算机视觉:朗伯光度立体法(Lambertian Photometric Stereo) 光度立体法简介朗伯光度立体法算法原理朗伯光度立体法matlab程序示例Albedo图Normal图Re_rendered图 参考文献 光度立体法简介 光度立体法,即Photometric Stereo, 最早…

Layui弹窗带标签可切换图表的应用Demo

提供Layui弹窗带页签的Demo写法 文章目录 前言一、展示效果二、详细代码1.代码2.简单释义 总结 前言 之前因为有需求,需要开发Layui的弹出框,同时弹窗框需要支持,页签点击切换内容,特此整理了这一篇文章,提供给需要的…
最新文章