软件质量与测试报告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)); // 库存已用完
    }
}
相关推荐
霍格沃兹测试开发学社测试人社区8 小时前
软件测试丨SDK 功能测试
软件测试·功能测试·测试开发
Algorithm-0078 小时前
【软件测试项目实战 】淘宝网:商品购买功能测试
功能测试
yaoyaoyao可爱呀2 天前
P14软件测试-功能测试
功能测试
qw9492 天前
Spring 6 第6章——单元测试:Junit
spring·junit·单元测试
逆风局?3 天前
JUnit单元测试
junit·单元测试
码明4 天前
SpringBoot整合junit
数据库·spring boot·junit
菁英猎人职业教育5 天前
信贷业务术语详解:深入理解金融领域的核心概念
软件测试·功能测试·金融·银行·零售·银行测试
程序员小远5 天前
如何使用Postman做接口自动化测试?
python·功能测试·测试工具·职场和发展·测试用例·postman·持续集成
大道之简6 天前
Mockito+PowerMock+Junit单元测试
junit·单元测试