软件质量与测试报告3-功能测试 JUnit与覆盖测试 EclEmma

目录

[一、 要求和目的](#一、 要求和目的)

[二、 环境和设备](#二、 环境和设备)

[三、 内容与步骤](#三、 内容与步骤)

[A. 日期推算器](#A. 日期推算器)

[B. 售货机程序](#B. 售货机程序)


不要问学长图为什么这么糊,问就是学长也是从别人那截图来的(图被截过多次,自然糊了),课太水了,一言难尽。差不多得了,90分太伤身体,85分就够了。

一、 要求和目的

本实验中,要求学生独立完成下面的内容:

  1. 学习并掌握 JUnit 的使用方法;

  2. 学习并掌握 EclEmma 的使用方法。

二、 环境和设备

本实验中需要:同前一个实验。

三、 内容与步骤

A. 日期推算器

请下载日期推算器程序(ST.emma.dayDiff),完成下列任务:

  1. 请对程序中的两个 Java 文件进行注释,特别是类和方法都需要注释;

①对于Day.java的注释如下:

②对于DayDiff.java的注释如下:

  1. 通过用 EclEmma 来执行 DayDiff 类,查看其代码覆盖情况;


3) 通过扩展 DayOff 的 main 函数来提高代码的覆盖率,要求至少两个类的覆盖率均达

到 90%以上;

  1. 请将 main 函数记录到实验报告上。
java 复制代码
/**
 * 主方法,用于测试 compute 方法
 */
public static void main(String[] args) {
    DayDiff dd = new DayDiff();

    // 测试用例 1: 正常情况下减去天数
    System.out.println(dd.compute(2015, 4, 8, -10)); // 输出 2015-3-29

    // 测试用例 2: 正常情况下加上天数
    System.out.println(dd.compute(2015, 4, 8, 10)); // 输出 2015-4-18

    // 测试用例 3: 跨年前加上天数
    System.out.println(dd.compute(2015, 12, 25, 10)); // 输出 2016-1-4

    // 测试用例 4: 跨年后减去天数
    System.out.println(dd.compute(2016, 1, 5, -10)); // 输出 2015-12-26

    // 测试用例 5: 加上大量天数,跨越多个年份
    System.out.println(dd.compute(2015, 1, 1, 800)); // 输出 2017-3-11

    // 测试用例 6: 减去大量天数,跨越多个年份
    System.out.println(dd.compute(2017, 3, 11, -800)); // 输出 2015-1-1

    // 测试用例 7: 在闰年中操作
    System.out.println(dd.compute(2020, 2, 29, 1)); // 输出 2020-3-1

    // 测试用例 8: 从闰年跨到非闰年
    System.out.println(dd.compute(2020, 2, 28, 1)); // 输出 2020-2-29

    // 测试用例 9: 非闰年中的2月
    System.out.println(dd.compute(2021, 2, 28, 1)); // 输出 2021-3-1

    // 测试用例 10: 加上0天
    System.out.println(dd.compute(2021, 6, 15, 0)); // 输出 2021-6-15
    // 错误1
    System.out.println(dd.compute(2024, 2, 30, 5)); // 2024年2月没有30号
    // 错误2
    System.out.println(dd.compute(2024, 13, 15, 5));// 月份超出了合法范围
    // 错误3
    System.out.println(dd.compute(2023, 2, 29, 5));// 2023年不是闰年,无法有2月29日
    // 错误4
    System.out.println(dd.compute(2024, 1, 0, 5));// 日期为零
}

程序存在的问题:

无法正确处理边界条件,对于不合法的输入没有进行校验。

B. 售货机程序

请编写实现一个售货机程序,其基本工作原理如下:

  1. 该售货机提供 beer 和 orange 两种饮料,每种饮料的价格都是 50 分;

  2. 两种饮料的初始库存都是 3,售货机内存有 50 分(5 角)硬币5 个和 100 分(1 元) 硬币 3 个;

  3. 用户通过投币和选择饮料类型实现自动购物,其中:

●硬币仅支持 50 分或 100 分 1 枚,其他硬币值不接受,否则提示"请投 5 角或者1 元的硬币。";

●如果用户选择了超出了 beer 和orange 的饮料,提示"目前不提供该饮料。";

●如果用户投入 50 分硬币,选择的饮料正好有库存,提示"请取饮料",否则已经 售完则提示"目前该饮料已经售完。";

●如果用户投入 100 分硬币,在上一种情况的基础上,还需检查是否机内存有 50 分硬币,如有则提示"请取饮料,并取回找钱。",否则提示"对不起,目前不能 找钱,请投 5 角硬币。";
●特别注意:上述描述仅为基本功能,其他相关操作需要独立思考并程序实现,比 如:提示"请取饮料"还需将该饮料库存减少一;等等。

  1. 请在 Eclipse 新建一个 SaleMachine 项目,并新建一个 SaleMachine 类,该类中有一 个方法:

public String buy(String t ype, int money);

其中 type 表示饮料类型,仅支持 beer 和 orange;money 是投币金额,仅支持 50 和 100; 返回值是显示的信息。

因果图如下

  1. 请编写 main 方法,自行测试程序,确保自己对程序功能满意,请将源程序记录到 实验报告中。
java 复制代码
// 售货机
public class SaleMachine {
    // 饮料库存
    private int beerStock = 3;
    private int orangeStock = 3;

    // 硬币库存
    private int fiftyCentsCoins = 5;
    private int oneDollarCoins = 3;

    /**
     * 用户购买饮料的方法
     * @param type 饮料类型,仅支持 beer 和 orange
     * @param money 投币金额,仅支持 50 和 100
     * @return 返回操作结果的信息
     */
    public String buy(String type, int money) {
        // 检查投币金额是否正确
        if (money != 50 && money != 100) {
            return "请投 5 角或者 1 元的硬币。";
        }

        // 检查饮料类型是否正确
        if (!type.equals("beer") && !type.equals("orange")) {
            return "目前不提供该饮料。";
        }

        // 处理购买逻辑
        if (type.equals("beer")) {
            if (beerStock == 0) {
                return "目前该饮料已经售完。";
            } else if (money == 50) {
                beerStock--;
                fiftyCentsCoins++;
                return "请取饮料";
            } else if (money == 100) {
                if (fiftyCentsCoins == 0) {
                    return "对不起,目前不能找钱,请投 5 角硬币。";
                } else {
                    beerStock--;
                    oneDollarCoins++;
                    fiftyCentsCoins--;
                    return "请取饮料,并取回找钱。";
                }
            }
        } else if (type.equals("orange")) {
            if (orangeStock == 0) {
                return "目前该饮料已经售完。";
            } else if (money == 50) {
                orangeStock--;
                fiftyCentsCoins++;
                return "请取饮料";
            } else if (money == 100) {
                if (fiftyCentsCoins == 0) {
                    return "对不起,目前不能找钱,请投 5 角硬币。";
                } else {
                    orangeStock--;
                    oneDollarCoins++;
                    fiftyCentsCoins--;
                    return "请取饮料,并取回找钱。";
                }
            }
        }
        return "未知错误。";
    }

    // 测试主方法
    public static void main(String[] args) {
        SaleMachine sm = new SaleMachine();

        // 测试用例
        System.out.println(sm.buy("beer", 50)); // 应输出:请取饮料
        System.out.println(sm.buy("orange", 50)); // 应输出:请取饮料
        System.out.println(sm.buy("beer", 100)); // 应输出:请取饮料,并取回找钱。
        System.out.println(sm.buy("orange", 100)); // 应输出:请取饮料,并取回找钱。
        System.out.println(sm.buy("beer", 100)); // 应输出:请取饮料,并取回找钱。
        System.out.println(sm.buy("beer", 50)); // 应输出:请取饮料
        System.out.println(sm.buy("beer", 50)); // 应输出:目前该饮料已经售完。
        System.out.println(sm.buy("beer", 100)); // 应输出:目前该饮料已经售完。
        System.out.println(sm.buy("orange", 100)); // 应输出:请取饮料,并取回找钱。
        System.out.println(sm.buy("orange", 100)); // 应输出:请取饮料,并取回找钱。
        System.out.println(sm.buy("orange", 50)); // 应输出:请取饮料
        System.out.println(sm.buy("orange", 50)); // 应输出:目前该饮料已经售完。
        System.out.println(sm.buy("orange", 100)); // 应输出:目前该饮料已经售完。
        System.out.println(sm.buy("coke", 50)); // 应输出:目前不提供该饮料。
        System.out.println(sm.buy("beer", 10)); // 应输出:请投 5 角或者 1 元的硬币。
    }
}
  1. 用 JUnit 测试售货机程序,步骤如下:

●请建立 SaleMachineTest 类,内容如下:

java 复制代码
import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class SaleMachineTest {
    //pick 4 beers one by one with 50 coin,
    //the message should be three times "ok" //and "failed" at the last time;
    @Test public void test_50Beer(){
        SaleMachinesm = new SaleMachine();
        assertEquals(sm.buy("beer", 50), "请取饮料"); assertEquals(sm.buy("beer", 50), "请取饮料"); assertEquals(sm.buy("beer", 50), "请取饮料");
        assertEquals(sm.buy("beer", 50), "目前该饮料已经售完。");
    } 
}

●点击"@Test public void test_50Beer()"行前错误标识处,添加 JUnit4 支持;

●运行这个测试类;

●运行结果应该如下图所示,否则请仔细检查程序;

●请参照"test50Beer()"编写下列测试方法:

投币 1 元购买橙汁四次;

投币 1 元购买橙汁三次,然后投币 1 元购买啤酒三次。

●用 EclEmma 进行覆盖测试,请设计新的测试用例以期尽可能的扩大整个项目的覆盖率, 要求整个工程的覆盖率至少达到 80% ,请将 测试方法和测试结果记录在试验报告上

覆盖率

测试结果

测试方法

java 复制代码
import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class SaleMachineTest {

    // 投币 50 分购买啤酒四次,前三次应该成功,第四次提示售完
    @Test
    public void test_50Beer() {
        SaleMachine sm = new SaleMachine();
        assertEquals("请取饮料", sm.buy("beer", 50));
        assertEquals("请取饮料", sm.buy("beer", 50));
        assertEquals("请取饮料", sm.buy("beer", 50));
        assertEquals("目前该饮料已经售完。", sm.buy("beer", 50));
    }

    // 投币 1 元购买橙汁四次,前三次应该成功并找零,第四次提示售完
    @Test
    public void test_100Orange() {
        SaleMachine sm = new SaleMachine();
        assertEquals("请取饮料,并取回找钱。", sm.buy("orange", 100));
        assertEquals("请取饮料,并取回找钱。", sm.buy("orange", 100));
        assertEquals("请取饮料,并取回找钱。", sm.buy("orange", 100));
        assertEquals("目前该饮料已经售完。", sm.buy("orange", 100));
    }

    // 投币 1 元购买橙汁三次,投币 1 元购买啤酒三次,前三次橙汁应该成功并找零
    // 第一次啤酒应成功并找零,后两次啤酒无法找零
    @Test
    public void test_100OrangeThen100Beer() {
        SaleMachine sm = new SaleMachine();
        assertEquals("请取饮料,并取回找钱。", sm.buy("orange", 100));
        assertEquals("请取饮料,并取回找钱。", sm.buy("orange", 100));
        assertEquals("请取饮料,并取回找钱。", sm.buy("orange", 100));
        assertEquals("请取饮料,并取回找钱。", sm.buy("beer", 100));
        assertEquals("请取饮料,并取回找钱。", sm.buy("beer", 100));
        assertEquals("对不起,目前不能找钱,请投 5 角硬币。", sm.buy("beer", 100));
    }

    // 投币金额不正确的情况
    @Test
    public void test_invalidCoin() {
        SaleMachine sm = new SaleMachine();
        assertEquals("请投 5 角或者 1 元的硬币。", sm.buy("beer", 25));
        assertEquals("请投 5 角或者 1 元的硬币。", sm.buy("orange", 75));
    }

    // 选择不存在的饮料类型
    @Test
    public void test_invalidDrink() {
        SaleMachine sm = new SaleMachine();
        assertEquals("目前不提供该饮料。", sm.buy("coke", 50));
        assertEquals("目前不提供该饮料。", sm.buy("water", 100));
    }

    // 测试库存和硬币数量上限情况
    @Test
    public void test_maximumCapacity() {
        SaleMachine sm = new SaleMachine();
        for (int i = 0; i < 100; i++) {
            sm.buy("beer", 100);
            sm.buy("orange", 100);
        }
        assertEquals("目前该饮料已经售完。", sm.buy("beer", 100)); // 库存已达上限
        assertEquals("对不起,目前不能找钱,请投 5 角硬币。", sm.buy("orange", 100)); // 50 分硬币用完
    }

    // 测试连续购买啤酒超出库存的情况
    @Test
    public void test_exceedBeerStock() {
        SaleMachine sm = new SaleMachine();
        assertEquals("请取饮料,并取回找钱。", sm.buy("beer", 100));
        assertEquals("请取饮料", sm.buy("beer", 50));
        assertEquals("请取饮料", sm.buy("beer", 50));
        assertEquals("目前该饮料已经售完。", sm.buy("beer", 50));
        assertEquals("目前该饮料已经售完。", sm.buy("beer", 50)); // 库存已用完
    }

    // 测试连续购买橙汁超出库存的情况
    @Test
    public void test_exceedOrangeStock() {
        SaleMachine sm = new SaleMachine();
        assertEquals("请取饮料,并取回找钱。", sm.buy("orange", 100));
        assertEquals("请取饮料", sm.buy("orange", 50));
        assertEquals("请取饮料", sm.buy("orange", 50));
        assertEquals("目前该饮料已经售完。", sm.buy("orange", 50));
        assertEquals("目前该饮料已经售完。", sm.buy("orange", 50)); // 库存已用完
    }
}
相关推荐
努力搬砖的小H7 小时前
FPGA应用技巧之Block Design基本使用方法
功能测试·fpga开发·zynq·block design
岁月失语唯石能言1 天前
《 Web项目测试实战:博客系统的功能/接口/自动化/性能全流程测试报告》
自动化测试·功能测试·selenium·jmeter·接口测试·压力测试·性能测试
PhotonixBay1 天前
InGaAs微透镜3D形貌怎么测?共聚焦显微镜在光通信的应用实践
功能测试·测试工具·3d·测试标准
Bug 挖掘机1 天前
网传阿里天猫超市技术近期迎来调整,前端和测试团队合并为“智能交付”团队
自动化测试·软件测试·功能测试·测试开发·ai测试
慧都小项2 天前
汽车工具链重复测试太耗人?用 TestComplete 自动跑
功能测试·回归·汽车·嵌入式·软件工程·测试覆盖率
新知图书3 天前
9.4 功能测试与效果验证
人工智能·功能测试
测试19983 天前
软件测试面试八股文【2026最新版】
自动化测试·软件测试·功能测试·测试工具·面试·职场和发展·测试用例
AI情绪识别开源5 天前
检信 ALLEMOTION OS 加密打包可执行程序 — 全面测试报告版本: v1.3功能测试 / 性能测试 /
开发语言·数据结构·人工智能·功能测试