• 测试与优化


    学号1:211606367 姓名:林恩 学号2:211606445 姓名:肖志豪

    一、预估与实际

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 30 30
    • Estimate • 估计这个任务需要多少时间 30 30
    Development 开发 690 650
    • Analysis • 需求分析 (包括学习新技术) 70 50
    • Design Spec • 生成设计文档 50 70
    • Design Review • 设计复审 20 30
    • Coding Standard • 代码规范 (为目前的开发制定合适的规范) 30 20
    • Design • 具体设计 185 185
    • Coding • 具体编码 185 185
    • Code Review • 代码复审 30 30
    • Test • 测试(自我测试,修改代码,提交修改) 120 120
    Reporting 报告 60 50
    • Test Repor • 测试报告 30 30
    • Size Measurement • 计算工作量 10 10
    • Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 10 20
    合计 780 730

    二、需求分析

    需要了解Junit如何使用以及相关要求:

    测试要求

    • 测试方法上必须使用@Test进行修饰
    • 测试方法必须使用public void进行修饰,不能带任何参数
    • 新建一个源代码目录来存放我们的测试代码
    • 测试类的包应该和被测试类保持一致
    • 测试单元中的每个方法必须可以独立测试,测试方法间不能有任何的依赖
    • 测试类使用Test作为类名的后缀(不是必须的)
    • 测试方法使用test作为方法名的前缀(不是必须的)

    测试失败的两种情况

    • Failure一般由单元测试使用的断言方法判断失败所引起的,这经表示测试点发现了问题,就是说程序输出的结果和我们预期的不一样
    • error是由代码异常引起的,他可以产生于测试代码本身的错误,也可以是被测试代码中的一个隐藏的bug
    • 测试用例不是用来证明你是对的,而是用来证明你没有错;即测试用例不能证明你逻辑上的错误,只能检测出你代码中的错误

    执行顺序

    @BeforeClass - @Before - @Test - @After - @AfterClass

    @BeforeClass:它会在所有方法运行前被执行,static修饰

    @Before:会在每一个测试方法被运行前执行一次

    @Test:将一个普通的方法修饰成为一个测试方法

    xx.class为捕获异常类

    @Test(expected = xx.class)

    @Test(timeout = 毫秒)

    @Ignore:所修饰的测试方法会被测试运行器忽略

    @RunWith:可以更改测试运行器 org.junit.runner.Runner

    @After:会在每一个测试方法运行后被执行一次

    @AfterClass:它会在所有方法运行结束后被执行,static修饰

    • @BeforeClass修饰的方法会在所有方法被调用前被执行
    • 而且该方法是静态的,所以当测试类被加载后接着就会运行它
    • 而且在内存中它只会存在一份实例,他比较适合加载配置文件
    • @AfterClass所修饰的方法通常用来对资源的清理,如关闭数据库的连接
    • @Before@After会在每个测试方法的前后各执行一次
    • @Before@After会在每个测试方法的前后各执行一次
    • @Before@After会在每个测试方法的前后各执行一次

    测试套件(批量执行测试用例)

    测试套件就是组织测试类一起运行的

    写一个作为测试套件的入口类,这个类里不包含其他的方法

    更改测试运行suit.class

    将要测试的类作为数组传入Suite.SuiteClasses({})

    @RunWith(Suite.class)

    @Suite.SuiteClasses({TaskTest1.class,TaskTest2.class,TaskTest3.class})

    Junit参数化测试

    更改默认的测试运行器为RunWith(Parameterized.class)

    声明变量来存放预期值和结果值

    声明一个返回值为Collection的公共静态方法,并使用@Parameters进行修饰

    为测试类声明一个带有参数的公共构造函数,并在其中为之声明变量赋值

    三、设计

    1. 设计思路

    说明你如何设计这个程序

    设计单元测试的思路

    • assertEquals()和assertRaises(),比对方法返回值和逻辑值的差别,来检验方法的是否执行有效成功
    • 若是有的方法没有返回值,则先实例化,然后比对方法中的值和逻辑值的差别也是可以的
    • 有些需要赋予某些其它的初始值

    单元测试

    • 部分单元测试代码

    请展示一段程序的关键代码,并解释代码的作用

        @Test
    	public void testMain() {
    		String[] args = {"-n", "100", "-grade", "3"};
    		MathExam math = new MathExam();
    		math.main(args);
    		assertEquals(true, math.output_boolean);
    	}
    

    测试方法上有@Test才会进行测试运算。先实例化,然后传参,math.output_boolean初值为false,执行完代码后math.output_boolean会赋值为true,代表执行完成。这时候只需要判断下值是否为true,即可代表main()是否执行成功。

    要对各种可能的值进行测试,确保能够实现方法的各种可能

    • 单元测试覆盖率截图

    单元测试覆盖率

    结构优化

    • UML类图:
    类图
    • 程序运行流程图
    流程图

    程序做出重构的部分,与重构的原因

    • 重构了关于两个数字的计算与判断,在原先代码里关于数字的计算判断大量重复,所以我将它生成为一个方法类与生成式子的类合并
    • 将生成式子的类从原先类中提取出,专门生成个类来生成式子以及判断,为了让每个类的模块与功能都更加精准、

    重构后每个模块的功能

    • MathExam类(主类,自身负责生成和写入文件,以及调用其它方法类来生成式子)
    • Two_Numbers类(负责生成一年级和二年级式子以及子式判重,防止生成重复的式子包括子式,在生成三年级式子时调用Calculation类)
    • Calculation类(负责三年级式子,转成中缀表达式以及后缀表达式求和)

    性能调优

    • 贴出优化前效能分析工具的结果截图
    性能调优前
    • 描述程序的性能瓶颈

      • 在代码中存在着大量的重复代码,有些代码冗余无法行之有效实现功能
    • 给出优化方案

      • 进行了一定量的代码缩减提取,删减某些无用或者重复的代码
    • 贴出优化后效能分析工具的结果截图

    性能调优后

    2. 实现方案 写出具体实现的步骤

    分为三个步骤:

    单元测试

    • 针对程序架构,进行单元测试,确保每个模块能够达到预期的要求

    结构优化

    • 把具有相似功能的代码封装在一起
    • 思考代码应该怎么进行结构优化
    • 每当代码的一个模块完成了重构,就需要commit
    • 为了保证每次重构后代码的正确性,我们需要先进行回归测试,再commit代码

    性能调优

    • 测试并改进程序生成四则运算算式的效率
    • 帮我们分析找到代码中执行效率最差,也就是所谓 效能瓶颈 的部分。就可以把精力花费在改进瓶颈上,从而高效快速地提升程序性能

    四、编码

    调试日志

    记录编码调试的日志,请记录下开发过程中的 debug 历程
    比如:

    • 在代码的什么位置,代码出现了什么问题,问题会导致什么结果,怎么解决的

      • 在调试代码时,一旦更改代码,也需要在测试代码处进行及时的相对应更改
      • 对参数的传递方式,有两种,值传递和引用传递,在方法传递的参数中是值传递,更改子方法中的的值是不会修改到父方法相对应的值
    • 请说明你如何按照设计思路进行编码,并记录你在开发中遇到的问题,与解决过程

      • 在写测试时,查找到有两种方法assertEquals()和assertRaises()。了解到这两种方法各自作用,通过比较object判断不同来返回测试结果,如果相同,测试通过;反之,不通过。这对方法的模块化程度有着一定的要求。后来我想了些方法,不必通过一定要有方法返回值来判断。因为实现方法后,方法内的某些参数必然改变,这时候只要检验到这个方法的应该实现的内容达到逻辑上的值即可。
      • 需要对代码的命名,意义,规范有着很深的认识,毕竟不仅仅是自己一个人在编程,需要让其他人看懂读懂,了解代码。也方便自己后期阅读,修改,重构。

    五、总结

    • 关于计算机题目重复特点,我总结了几个:
      • 题目完全相同
      • 题目不同,在顺序上不同,式子不同,但是子式相同,只是改变了形式。其实实质是相同的,结果相同
      • 比如a + b和b +a,a x b和b x a,
      • 最终决定在生成式子时,加上一个采集子式的集合用来判断子式是否重复
  • 相关阅读:
    Django_redis_session
    python_redis操作
    Django_url反向解析
    Django_分页
    Django_cookie与sesstion
    Django 自定义错误页面 403 404...
    Django_设置静态文件、上传文件
    Django设置子路由
    nginx、uwsgi
    CentOS安装MySQL
  • 原文地址:https://www.cnblogs.com/mumuyinxin/p/9716045.html
Copyright © 2020-2023  润新知