如何将JUnit测试用例中的多个输入模拟到我的程序中?

时间:2016-09-19 09:42:14

标签: java junit

我写了一个看起来像这样的程序:

import java.util.Scanner;
import java.util.ArrayList;

public class Triangles {

    public static void main(String[] args) {

        Scanner user_input = new Scanner(System.in);

        ArrayList<String> triangleLengths = new ArrayList<String>();

        for (int i=0; i < 3; i++) {

            System.out.print("Triangle length #" + i + ": ");
            triangleLengths.add(i,user_input.next());   
        }

        if (triangleLengths.get(0) == triangleLengths.get(1) && triangleLengths.get(1) == triangleLengths.get(2)) {

            System.out.println("This triangle is an equilateral triangle");

        } else if (triangleLengths.get(0) == triangleLengths.get(1) || triangleLengths.get(0) == triangleLengths.get(2) || triangleLengths.get(1) == triangleLengths.get(2)) {

            System.out.println("This triangle is an isosceles triangle");

        } else if (triangleLengths.get(0) != triangleLengths.get(1) && triangleLengths.get(1) != triangleLengths.get(2)) {

            System.out.println("This triangle is a scalene triangle");

        } else {

            System.out.println("The input does not make a triangle!");

        }


    }

}

我的任务是编写一个JUnit测试用例,通过各种输入测试来实际尝试“打破”我的程序。我不能为我的生活弄清楚如何做这个作为一个完整的Java新手 - 有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分:1)

所以我提出了如何解决它的建议。

你想做到这一点,你可以自动测试不同的参数,而无需手动输入,所以我将三角形部分隔离,如下所示。

编辑:我在某种程度上重新编写代码

正常运行类 src / main.java

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner user_input = new Scanner(System.in);
        List<String> triangleLengths = new ArrayList<>();

        for (int i = 0; i < 3; i++) {
            System.out.print("Triangle length #" + i + ": ");
            triangleLengths.add(i, user_input.next());
        }

        // Result output will be here
        Triangle subject = new Triangle(triangleLengths);
        if (subject.getTriangleType() == Triangle.Type.INVALID) {
            System.out.println("Triangle is invalid");
        } else {
            System.out.println("Triangle is: " + subject.getTriangleType());
        }
    }
}

JUnit类 test / TrianglesTest.java

import org.junit.Test;

import java.util.Arrays;
import java.util.List;

import static org.junit.Assert.assertEquals;

public class TrianglesTest {

    /**
     * Testing with String inputs (what you'd enter manually)
     */
    @Test
    public void testWithStrings() {
        List<String> triangleLengths = Arrays.asList("len1", "len2", "len3");

        Triangle subject = new Triangle(triangleLengths);
        // Example of checking if expected type
        assertEquals(Triangle.Type.ISOSCELES, subject.getTriangleType());
    }

    /**
     * Testing with numbers as what I'd expect the triangle to be made of
     *
     * Here you test with a triangle object
     *
     * Haven't tested what the 3 types is sorry :O
     */
    @Test
    public void testWithNumbersAsObject() {
        Triangle subject = new Triangle(4, 5.32, 7);
        assertEquals(Triangle.Type.SCALENE, subject);
    }

    /**
     * This piece you check the static method but have no object
     */
    @Test
    public void testWithNumbersStaticMethod() {
        assertEquals(Triangle.Type.ISOSCELES, Triangle.getTriangleType(3.4d, 4d, 1.111d));
    }
}

最后你要测试的实际代码 src / Triangles.java

import java.util.List;

/**
 * I created so you can both have an object of the triangle or make the check purely static
 * maybe you need an object type for later?
 */
public class Triangle {

    final double side0;
    final double side1;
    final double side2;

    public Triangle(List<String> triangleLengths) {
        this(Double.parseDouble(triangleLengths.get(0)),
                Double.parseDouble(triangleLengths.get(1)),
                Double.parseDouble(triangleLengths.get(2)));
    }

    public Triangle(double side0, double side1, double side2) {
        this.side0 = side0;
        this.side1 = side1;
        this.side2 = side2;
    }

    public Triangle.Type getTriangleType() {
        return Triangle.getTriangleType(side0, side1, side2);
    }

    public static Triangle.Type getTriangleType(double side0, double side1, double side2) {
        if (isEquilateral(side0, side1, side2)) {
            return Type.EQUILATERAL;
        } else if (isIsosceles(side0, side1, side2)) {
            return Type.ISOSCELES;
        } else if (isScalene(side0, side1, side2)) {
            return Type.SCALENE;
        } else {
            return Type.INVALID;
        }
    }

    private static boolean isScalene(double side0, double side1, double side2) {
        return side0 != side1 && side1 != side2;
    }

    private static boolean isIsosceles(double side0, double side1, double side2) {
        return side0 == side1 || side0 == side2 || side1 == side2;
    }

    private static boolean isEquilateral(double side0, double side1, double side2) {
        return side0 == side1 && side1 == side2;
    }

    public enum Type {
        EQUILATERAL,
        ISOSCELES,
        SCALENE,
        INVALID
    }
}

希望这有帮助。

请注意,我从三角形类返回答案,而不是立即写出来。只有在手动运行中,我才从主方法中写出来。

答案 1 :(得分:0)

Wisienkas的答案是正确的;但我认为更多的概念背景会有所帮助。

当你开始编码时,你会看到来自 stdin 的“用户输入”,使用扫描仪,就像“大事”一样。你取一些值,对它做一些处理;并打印一些结果。

问题是:那不是“现实世界”的运作方式;因此,您遇到了代码无法测试的问题。这里要理解的关键是:为了让事情变得更好,你需要一点点抽象。

那些是:

  1. 您的“处理”代码会进入自己的类和方法。理想情况下,那些方法除了在调用时作为参数处理的数据。
  2. 您的“处理”代码应返回其结果。当你只是打印到System.out时,几乎不可能验证一些代码正在做什么。

答案 2 :(得分:0)

您要做的最好的事情是重新设计代码,以便

  • 三角形逻辑在它自己的类中,
  • 用户输入逻辑采用自己的方法,
  • main方法绝对是最小的。

然后,您可以单独测试三角逻辑和用户输入逻辑。如果main足够小,你可以在不编写单元测试的情况下离开。

但是,不是你问的是什么。如果您希望在编写代码时完全,则可以通过将System.inSystem.out设置为控制输入和输出的流来测试它。< / p>

您的测试类可能看起来像这样。这会将System.in重定向到从您在每个测试中指定的String中读取,并System.out写入您之后可以验证其内容的流。

public class TrianglesTest {
    @Test
    public void identifiesEquilateralTriangle() {
        ByteArrayOutputStream output = setStreams("5 5 5 ");
        Triangles.main(new String[0]);
        assertEquals("This triangle is an equilateral triangle", output.toString().trim());
    }

    // Plus a whole lot more tests for other cases

    private ByteArrayOutputStream setStreams(String input) {
        System.setIn(new ByteArrayInputStream(input.getBytes()));
        ByteArrayOutputStream toReturn = new ByteArrayOutputStream();
        System.setOut(new PrintStream(toReturn));
        return toReturn;
    }
}