是什么导致 JUnit 和系统规则在此学生的提交上失败?

What is causing to JUnit and System Rules to fail on this Student's Submission?

过去一个月我一直在使用自动评分器,而我的一位理解 material 的学生似乎由于返回 'null' 而不断使我的 JUnit 测试用例失败。因为是Java我的课程,他们暂时还在用System.out.println()。因此,我使用 System Rules 来解析他们的输出。

学生的提交:

import  java.util.Scanner;

public class DistanceFormula {
     public static void main(String[] args) {

    //Declarations
    double distance;
    double differenceX;
    double differenceY;
    double firstX;
    double secondX;
    double firstY;
    double secondY;

    //User Input for the First X value (X value for Point 1)
    System.out.println("Enter In The value of X for point 1:");
    Scanner inputFirstX = new Scanner(System.in);
    firstX = inputFirstX.nextDouble();

    //User Input for the First Y value  (Y value for Point 1)
    System.out.println("Enter In The value of Y for point 1:");
    Scanner inputFirstY = new Scanner(System.in);
    firstY = inputFirstY.nextDouble();

    //User Input for Second X value (X value for point 2)
    System.out.println("Enter In The value of X for point 2:");
    Scanner inputSecondX = new Scanner(System.in);
    secondX = inputSecondX.nextDouble();

    //User Input for Second Y value (Y value for point 2)
    System.out.println("Enter In The value of Y for point 2:");
    Scanner inputSecondY = new Scanner(System.in);
    secondY = inputSecondY.nextDouble();

    //Find the difference of each point
    differenceX = secondX - firstX;
    differenceY = secondY - firstY;

    //Distance Formula
    distance = Math.sqrt((Math.pow(differenceX, 2)) + (Math.pow(differenceY, 2)));

    //Displaying the outcome
    System.out.println("Your First Point: " + firstX + "," + firstY + "\n" + "Your Second Point: " + 
    secondX + "," + secondY + "\n"  + "The distance between the two points is: " + distance);
     }
}

我的一个测试用例:

@Rule
public final StandardOutputStreamLog outlog = new StandardOutputStreamLog();

@Rule
public final TextFromStandardInputStream systemInMock = emptyStandardInputStream();
...
@Test(timeout=5000)
public void tests1() {
    double x1 = 5.0;
    double y1 = 5.0;
    double x2 = 4.5;
    double y2 = 4.5;
    systemInMock.provideText(x1+"\n"+y1+"\n"+x2+"\n"+y2+"\n");
    TestFile.main(new String[]{});
    String reality = outlog.getLog().toLowerCase();
    double calc = distance(x1,y1,x2,y2);
    boolean result = reality.contains(calc+"");
    assertTrue("Testing "+x1+" "+y1+" "+x2+" "+y2+" ", result);
}

最后,我的 TestRunner:

// JUnit
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

// SimpleJSON
import org.json.simple.JSONObject;
import org.json.simple.JSONArray;

public class TestRunner {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        JSONObject obj = new JSONObject();
        Result result = JUnitCore.runClasses(TestJunit.class);

        double tests = result.getRunCount();
        double fails = result.getFailureCount();
        obj.put("tests", tests);
        obj.put("fails", fails);

        //System.out.println("Testing Complete\n---------------------------");
        //System.out.printf("Run Time of Tests:\t%d ms\n", result.getRunTime());
        //System.out.printf("Number of Tests:\t%d\n", (int)tests);

        if (result.wasSuccessful()){
            //System.out.println("All Tests Successful");
        } else {
            //System.out.println("Test Fails\n---------------------------");
            JSONArray failures = new JSONArray();
            System.out.printf("Number of Fails:\t%d\n", (int)fails);
            for (Failure failure : result.getFailures()) {
                String header = failure.getTestHeader();
                String msg = failure.getMessage();
                if (msg.contains("timed out")){
                    failures.add(header + " " + msg);
                    System.out.println(header + " " + msg);
                } else {
                    failures.add(msg);
                    System.out.println(msg);
                }
                obj.put("failures", failures);
            }
        }

        //System.out.println("Results\n---------------------------");
        double grade = 100.0 * (double)((tests - fails)/tests);
        obj.put("grade", grade);
        System.out.printf("Grade:\t\t\t%.1f%%\n", grade);
        System.out.print("JSON:\n");
        System.out.println(obj);
    }
} 

在 TestRunner 中 if (msg.contains("timed out")) 会出错,因为 msg 是 null

如果我 运行 学生的代码或测试其他人的工作,测试 运行 完全没问题。如果这是我的问题,我想修复它。谢谢!

Scanner 是缓冲的,因此每个构造的实例都消耗了来自模拟 System.in 的文本,而不是 nextDouble 所需的文本。下一个 Scanner 尝试读取同一底层流中剩余的内容,但输入已被消耗,因此 nextDouble 抛出 NoSuchElementException.

您可以尝试通过返回更少的字节(但不指示流的结尾)来更准确地模拟 System.in,直到检测到对 System.out 的下一次调用,或者更改方法并使用 Runtime.exec 生成新的 JVM 并捕获该进程的所有输出。

问题已在系统规则 1.11.0 中修复。您必须提供多行:

systemInMock.provideLines(
  Double.toString(x1),
  Double.toString(y1),
  Double.toString(x2),
  Double.toString(y2));