边界值分析法测试用例设计实例

简介: 边界值分析法是黑盒测试的重要方法,本文以一道数位DP算法题为例,自主测试黑盒测试用例,并采用JUnit5完成单元测试。

软件测试

题目描述

原题链接:洛谷 P2602 [ZJOI2010] 数字计数

输入两个正整数a,b,求在[a,b]中的所有整数中,每个数码(0\~9)各出现了多少次。

输入格式:

输入两个正整数a, b确定区间[a,b](0<a<b<10^13)。

输出格式:

在一行中输出0\~9每个数码在[a,b]区间内共出现多少次,用空格隔开。

输入样例1:

1 20

输出样例1:

2 12 3 2 2 2 2 2 2 2

输入样例2:

101 300

输出样例2:

40 139 140 41 40 40 40 40 40 40

输入样例3:

1 99

输出样例3:

9 20 20 20 20 20 20 20 20 20

实现代码

方法:数位DP。

public class DigitCount {

    private static final int DIGIT_NUM = 10, INIT_SIZE = 20;

    private static void solve(long x, long[] count, long[] ten, long[] dp) {
        int[] num = new int[INIT_SIZE];
        int len = 0;
        while (x > 0) {
            num[++len] = (int) (x % DIGIT_NUM);
            x = x / DIGIT_NUM;
        }
        for (int i = len; i >= 1; i--) {
            for (int j = 0; j <= DIGIT_NUM - 1; j++) {
                count[j] += dp[i - 1] * num[i];
            }
            for (int j = 0; j < num[i]; j++) {
                count[j] += ten[i - 1];
            }
            long num2 = 0;
            for (int j = i - 1; j >= 1; j--) {
                num2 = num2 * DIGIT_NUM + num[j];
            }
            count[num[i]] += num2 + 1;
            count[0] -= ten[i - 1];
        }
    }

    public static long[] digitCount(long a, long b) throws NumberOutOfBoundException, ANoLessThanBException {
        final long lowerBound = 0, upperBound = 10_000_000_000_000L;
        final int initDpSize = 15;
        if (a <= lowerBound || b <= lowerBound || a >= upperBound || b >= upperBound) {
            throw new NumberOutOfBoundException();
        }
        if (a >= b) {
            throw new ANoLessThanBException();
        }
        long[] result = new long[DIGIT_NUM];
        long[] ten = new long[INIT_SIZE];
        long[] dp = new long[INIT_SIZE];
        long[] countA = new long[INIT_SIZE];
        long[] countB = new long[INIT_SIZE];
        ten[0] = 1;
        for (int i = 1; i <= initDpSize; i++) {
            dp[i] = dp[i - 1] * DIGIT_NUM + ten[i - 1];
            ten[i] = DIGIT_NUM * ten[i - 1];
        }
        solve(a - 1, countA, ten, dp);
        solve(b, countB, ten, dp);
        for (int i = 0; i < DIGIT_NUM; i++) {
            result[i] = countB[i] - countA[i];
        }
        return result;
    }

}

设计测试用例

ID Input a Input b Output
1 1 1000000 488895, 600001, 600000, 600000, 600000, 600000, 600000, 600000, 600000, 600000
2 2 1000000 488895, 600000, 600000, 600000, 600000, 600000, 600000, 600000, 600000, 600000
3 1000000 999999999998 1088888400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000, 1199999399988
4 1000000 999999999999 1088888400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000, 1199999400000
5 1 2 0, 1, 1, 0, 0, 0, 0, 0, 0, 0
6 1 999999999998 1088888888889, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1199999999988
7 2 999999999998 1088888888889, 1199999999999, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1199999999988
8 1 999999999999 1088888888889, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000
9 2 999999999999 1088888888889, 1199999999999, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000, 1200000000000
10 999999999998 999999999999 0, 0, 0, 0, 0, 0, 0, 0, 1, 23
11 0 1 NumberOutOfBoundException
12 0 2 NumberOutOfBoundException
13 0 1000000 NumberOutOfBoundException
14 0 999999999998 NumberOutOfBoundException
15 0 999999999999 NumberOutOfBoundException
16 0 10000000000000 NumberOutOfBoundException
17 1 10000000000000 NumberOutOfBoundException
18 2 10000000000000 NumberOutOfBoundException
19 1000000 10000000000000 NumberOutOfBoundException
20 999999999998 10000000000000 NumberOutOfBoundException
21 999999999999 10000000000000 NumberOutOfBoundException
22 1000000 1000000 ANoLessThanBException
23 999999999998 1000000 ANoLessThanBException
24 1 1 ANoLessThanBException
25 999999999998 2 ANoLessThanBException

执行测试用例

基于Maven引入JUnit5框架,主要基于org.junit.jupiter.api.Testorg.junit.jupiter.api.Assertions即可完成任务。

基本的测试思路:

  • 如果是正常情况:

    Assertions.assertDoesNotThrow(() -> {
        Assertions.assertArrayEquals(expectedArray, DigitCount.digitCount(a, b));
    });
  • 如果是异常情况:

    Assertions.assertThrows(XXXException.class, () -> DigitCount.digitCount(a, b));

正常情况可以套在一个确保非异常的Lambda表达式中执行;而异常情况则应该单测,防止一处异常全体异常。

美中不足的点是魔法数的大量引入。

测试代码:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class DigitCountTest {

    @Test
    public void demoTest() {
        Assertions.assertDoesNotThrow(() -> {
            long[] expectedArray1 = new long[]{2, 12, 3, 2, 2, 2, 2, 2, 2, 2};
            long[] actualArray1 = DigitCount.digitCount(1, 20);
            Assertions.assertArrayEquals(expectedArray1, actualArray1);
            long[] expectedArray2 = new long[]{40, 139, 140, 41, 40, 40, 40, 40, 40, 40};
            long[] actualArray2 = DigitCount.digitCount(101, 300);
            Assertions.assertArrayEquals(expectedArray2, actualArray2);
        });
    }

    @Test
    public void normalTest() {
        Assertions.assertDoesNotThrow(() -> {
            Assertions.assertArrayEquals(new long[]{488895, 600001, 600000, 600000, 600000, 600000, 600000, 600000, 600000, 600000}, DigitCount.digitCount(1, 1000000));
            Assertions.assertArrayEquals(new long[]{488895, 600000, 600000, 600000, 600000, 600000, 600000, 600000, 600000, 600000}, DigitCount.digitCount(2, 1000000));
            Assertions.assertArrayEquals(new long[]{1088888400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999399988L}, DigitCount.digitCount(1000000, 999999999998L));
            Assertions.assertArrayEquals(new long[]{1088888400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L, 1199999400000L}, DigitCount.digitCount(1000000, 999999999999L));
            Assertions.assertArrayEquals(new long[]{0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, DigitCount.digitCount(1, 2));
            Assertions.assertArrayEquals(new long[]{1088888888889L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1199999999988L}, DigitCount.digitCount(1, 999999999998L));
            Assertions.assertArrayEquals(new long[]{1088888888889L, 1199999999999L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1199999999988L}, DigitCount.digitCount(2, 999999999998L));
            Assertions.assertArrayEquals(new long[]{1088888888889L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L}, DigitCount.digitCount(1, 999999999999L));
            Assertions.assertArrayEquals(new long[]{1088888888889L, 1199999999999L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L, 1200000000000L}, DigitCount.digitCount(2, 999999999999L));
            Assertions.assertArrayEquals(new long[]{0, 0, 0, 0, 0, 0, 0, 0, 1, 23}, DigitCount.digitCount(999999999998L, 999999999999L));
        });
    }

    @Test
    public void aNoLessThanBTest() {
        Assertions.assertThrows(ANoLessThanBException.class, () -> DigitCount.digitCount(1000000, 1000000));
        Assertions.assertThrows(ANoLessThanBException.class, () -> DigitCount.digitCount(999999999998L, 1000000));
        Assertions.assertThrows(ANoLessThanBException.class, () -> DigitCount.digitCount(1, 1));
        Assertions.assertThrows(ANoLessThanBException.class, () -> DigitCount.digitCount(999999999998L, 2));
    }

    @Test
    public void AOrBOutOfBoundTest() {
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(0, 1));
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(0, 2));
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(0, 1000000));
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(0, 999999999998L));
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(0, 999999999999L));
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(0, 10000000000000L));
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(1, 10000000000000L));
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(2, 10000000000000L));
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(1000000, 10000000000000L));
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(999999999998L, 10000000000000L));
        Assertions.assertThrows(NumberOutOfBoundException.class, () -> DigitCount.digitCount(999999999999L, 10000000000000L));
    }

}
相关文章
|
2月前
|
缓存 监控 算法
软件测试中的性能瓶颈分析与优化策略
【10月更文挑战第6天】 性能测试是确保软件系统在高负载条件下稳定运行的重要手段。本文将深入探讨性能测试的常见瓶颈,包括硬件资源、网络延迟和代码效率等问题。通过具体案例分析,我们将展示如何识别并解决这些问题,从而提升软件的整体性能。最后,文章还将分享一些实用的性能优化技巧,帮助读者在日常开发和测试中更好地应对性能挑战。
125 3
|
3月前
|
监控 测试技术 持续交付
软件测试中的性能瓶颈分析与优化策略
性能瓶颈,如同潜伏于软件深处的隐形障碍,悄然阻碍着系统的流畅运行。本文旨在揭示这些瓶颈的形成机理,剖析其背后的复杂成因,并汇聚一系列针对性的优化策略,为软件开发者提供一套系统性的解决方案。
62 5
|
1天前
|
开发框架 .NET Java
C#集合数据去重的5种方式及其性能对比测试分析
C#集合数据去重的5种方式及其性能对比测试分析
24 10
|
1月前
|
数据采集 自然语言处理 数据库
深入体验阿里云通义灵码:测试与实例展示
阿里云通义灵码是一款强大的代码生成工具,支持自然语言描述需求,快速生成高质量代码。它在测试、代码质量和用户体验方面表现出色,能够高效地生成 Python 和 Java 等语言的代码,助力开发者提升开发效率和代码质量。无论是新手还是资深开发者,都能从中受益匪浅。
深入体验阿里云通义灵码:测试与实例展示
|
28天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
62 1
|
2月前
|
机器学习/深度学习 JSON 算法
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
本文详细介绍了使用YOLOv5-Seg模型进行图像分割的完整流程,包括图像分割的基础知识、YOLOv5-Seg模型的特点、环境搭建、数据集准备、模型训练、验证、测试以及评价指标。通过实例代码,指导读者从自定义数据集开始,直至模型的测试验证,适合深度学习领域的研究者和开发者参考。
975 3
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
|
2月前
|
缓存 监控 测试技术
软件测试中的性能瓶颈分析与优化策略
本文深入探讨了在软件测试过程中,如何有效地识别和解决性能瓶颈问题。通过对性能瓶颈的定义、分类以及常见原因的分析,结合实际案例,提出了一系列针对性的优化策略和方法。这些策略旨在帮助测试人员和开发人员提高软件的性能表现,确保软件在高负载条件下依然能够稳定运行。
|
3月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
57 2
|
3月前
|
测试技术 持续交付 UED
软件测试的艺术与科学:平衡创新与质量的探索在软件开发的波澜壮阔中,软件测试如同灯塔,指引着产品质量的方向。本文旨在深入探讨软件测试的核心价值,通过分析其在现代软件工程中的应用,揭示其背后的艺术性与科学性,并探讨如何在追求技术创新的同时确保产品的高质量标准。
软件测试不仅仅是技术活动,它融合了创造力和方法论,是软件开发过程中不可或缺的一环。本文首先概述了软件测试的重要性及其在项目生命周期中的角色,随后详细讨论了测试用例设计的创新方法、自动化测试的策略与挑战,以及如何通过持续集成/持续部署(CI/CD)流程优化产品质量。最后,文章强调了团队间沟通在确保测试有效性中的关键作用,并通过案例分析展示了这些原则在实践中的应用。
96 1
|
3月前
|
监控 算法 测试技术
软件测试中的性能瓶颈分析与优化策略
本文旨在深入探讨软件测试过程中性能瓶颈的识别与优化方法。通过对性能瓶颈的概念、分类及其成因进行分析,结合实际案例,提出一套系统的性能瓶颈诊断流程和针对性的优化策略。文章首先概述了性能瓶颈的基本特征,随后详细介绍了内存泄漏、资源竞争、算法效率低下等常见瓶颈类型,并阐述了如何通过代码审查、性能监测工具以及负载测试等手段有效定位问题。最后,结合最佳实践,讨论了代码级优化、系统配置调整、架构改进等多方面的解决措施,旨在为软件开发和测试人员提供实用的性能优化指导。
99 4