我一直在努力测试if else和for循环这里是示例你能请求指导我如何自动化测试实际上适用于这些 语句?
for (int i=1; i<=10; i++){ // for loop from 1 to 10
System.out.println(" guess "+i+ ":");
int guess = scan.nextInt();
//if guess is greater than number entered
if(guess>number)
System.out.println("Clue: lower");
//if guess is less than number entered
else if (guess<number )
System.out.println("Clue: Higher");
//if guess is equal than number entered
else if(guess==number) {
System.out.println("Correct answer after only "+ i + " guesses – Excellent!");
}
答案 0 :(得分:3)
public class Main {
public static void main(String[] args) {
new Game().run();
}
}
public class Game {
public void run() {
Scanner scan = new Scanner(System.in);
int number = new Random().nextInt(100);
for (int i = 1; i <= 10; i++) {
System.out.println(" guess " + i + ":");
int guess = scan.nextInt();
if (guess > number) {
System.out.println("Clue: lower");
} else if (guess < number) {
System.out.println("Clue: Higher");
} else if (guess == number) {
System.out.println("Correct answer after only " + i + " guesses – Excellent!");
}
}
}
}
所有这些操作都应该通过IDE重构 - 移动方法,提取到字段,创建构造函数,将初始化器移动到构造函数,提取到参数等。
public class Main {
public static void main(String[] args) {
Game game = new Game(new Scanner(System.in), System.out, new Random().nextInt(100));
game.run();
}
}
public class Game {
private final Scanner scanner;
private final PrintStream printStream;
private final int number;
public Game(Scanner scanner, PrintStream out, int number) {
this.scanner = scanner;
this.printStream = out;
this.number = number;
}
public void run() {
for (int i = 1; i <= 10; i++) {
printStream.println(" guess " + i + ":");
int guess = scanner.nextInt();
if (guess > number) {
printStream.println("Clue: lower");
} else if (guess < number) {
printStream.println("Clue: Higher");
} else if (guess == number) {
printStream.println("Correct answer after only " + i + " guesses – Excellent!");
}
}
}
}
尝试模拟java.util.Scanner
您很快就会发现该类是最终的,因此我们创建了一个简单的包装器,并将java.util.Scanner
替换为Main
和Game
类中的一个
public class MyScanner {
private final Scanner scanner = new Scanner(System.in);
public int nextInt() {
return scanner.nextInt();
}
}
import org.junit.Test;
import org.mockito.InOrder;
import java.io.PrintStream;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class GameTest {
private final MyScanner scanner = mock(MyScanner.class);
private final PrintStream printStream = mock(PrintStream.class);
private final Game game = new Game(scanner, printStream, 15);
@Test
public void returnsCorrectOutputWhenNumberGuessedAfterThreeAttempts() {
when(scanner.nextInt()).thenReturn(10, 20, 15);
game.run();
InOrder inOrder = inOrder(scanner, printStream);
inOrder.verify(printStream).println(" guess 1:");
inOrder.verify(scanner).nextInt();
inOrder.verify(printStream).println("Clue: Higher");
inOrder.verify(printStream).println(" guess 2:");
inOrder.verify(scanner).nextInt();
inOrder.verify(printStream).println("Clue: lower");
inOrder.verify(printStream).println(" guess 3:");
inOrder.verify(scanner).nextInt();
inOrder.verify(printStream).println("Correct answer after only 3 guesses – Excellent!");
}
}
在循环中有3种可能的流程,我们有10次迭代。这总共提供了3 ^ 10~60.000个可能的流量。而且我们不想写6万个测试。因此我们再次重构(仅使用IDE重构选项)以达到以下状态。注意,所有都应该编译,测试应该仍然是绿色。
public class Main {
public static void main(String[] args) {
Game game = new Game(new SingleGuessHandler(new MyScanner(), System.out), new Random().nextInt(100));
game.run();
}
}
public class Game {
private final SingleGuessHandler singleGuessHandler;
private final int number;
public Game(SingleGuessHandler singleGuessHandler, int number) {
this.singleGuessHandler = singleGuessHandler;
this.number = number;
}
public void run() {
for (int i = 1; i <= 10; i++) {
singleGuessHandler.runSingleGuess(i, number);
}
}
}
public class SingleGuessHandler {
private final MyScanner scanner;
private final PrintStream printStream;
public SingleGuessHandler(MyScanner scanner, PrintStream printStream) {
this.scanner = scanner;
this.printStream = printStream;
}
public void runSingleGuess(int attempt, int number) {
printStream.println(" guess " + attempt + ":");
int guess = scanner.nextInt();
if (guess > number) {
printStream.println("Clue: lower");
} else if (guess < number) {
printStream.println("Clue: Higher");
} else if (guess == number) {
printStream.println("Correct answer after only " + attempt + " guesses – Excellent!");
}
}
}
public class MyScanner {
private final Scanner scanner = new Scanner(System.in);
public int nextInt() {
return scanner.nextInt();
}
}
public class GameTest {
private final MyScanner scanner = mock(MyScanner.class);
private final PrintStream printStream = mock(PrintStream.class);
private final Game game = new Game(new SingleGuessHandler(scanner, printStream), 15);
@Test
public void returnsCorrectOutputWhenNumberGuessedAfterThreeAttempts() {
when(scanner.nextInt()).thenReturn(10, 20, 15);
game.run();
InOrder inOrder = inOrder(scanner, printStream);
inOrder.verify(printStream).println(" guess 1:");
inOrder.verify(scanner).nextInt();
inOrder.verify(printStream).println("Clue: Higher");
inOrder.verify(printStream).println(" guess 2:");
inOrder.verify(scanner).nextInt();
inOrder.verify(printStream).println("Clue: lower");
inOrder.verify(printStream).println(" guess 3:");
inOrder.verify(scanner).nextInt();
inOrder.verify(printStream).println("Correct answer after only 3 guesses – Excellent!");
}
}
我们现有的GameTest
测试了几个课程,但现在我们只想测试Game
和SingleGuessHandler
的互动。在这一点上,我已经意识到你的原始代码没有包含任何逻辑来处理正确猜测的循环。这使得下面的单元测试变得更加简单,否则runSingleGuess
必须返回true / false值(表示是否再次调用它),我们将不得不再写一次测试以检查它是否返回false
,然后它不再被调用。简而言之:
@Test
public void callsSingleGuessHandlerTenTimes() {
SingleGuessHandler singleGuessHandler = mock(SingleGuessHandler.class);
Game game = new Game(singleGuessHandler, 17);
game.run();
InOrder inOrder = inOrder(singleGuessHandler);
inOrder.verify(singleGuessHandler).runSingleGuess(1, 17);
inOrder.verify(singleGuessHandler).runSingleGuess(2, 17);
inOrder.verify(singleGuessHandler).runSingleGuess(3, 17);
inOrder.verify(singleGuessHandler).runSingleGuess(4, 17);
inOrder.verify(singleGuessHandler).runSingleGuess(5, 17);
inOrder.verify(singleGuessHandler).runSingleGuess(6, 17);
inOrder.verify(singleGuessHandler).runSingleGuess(7, 17);
inOrder.verify(singleGuessHandler).runSingleGuess(8, 17);
inOrder.verify(singleGuessHandler).runSingleGuess(9, 17);
inOrder.verify(singleGuessHandler).runSingleGuess(10, 17);
inOrder.verifyNoMoreInteractions();
}
public class SingleGuessHandlerTest {
private final MyScanner scanner = mock(MyScanner.class);
private final PrintStream printStream = mock(PrintStream.class);
private final SingleGuessHandler singleGuessHandler = new SingleGuessHandler(scanner, printStream);
@Test
public void printsLowerClue() {
when(scanner.nextInt()).thenReturn(5);
singleGuessHandler.runSingleGuess(99, 4);
InOrder inOrder = inOrder(scanner, printStream);
inOrder.verify(printStream).println(" guess 99:");
inOrder.verify(scanner).nextInt();
inOrder.verify(printStream).println("Clue: lower");
inOrder.verifyNoMoreInteractions();
}
@Test
public void printsHigherClue() {
when(scanner.nextInt()).thenReturn(16);
singleGuessHandler.runSingleGuess(2, 100);
InOrder inOrder = inOrder(scanner, printStream);
inOrder.verify(printStream).println(" guess 2:");
inOrder.verify(scanner).nextInt();
inOrder.verify(printStream).println("Clue: Higher");
inOrder.verifyNoMoreInteractions();
}
@Test
public void printsSuccessfulGuessMessage() {
when(scanner.nextInt()).thenReturn(65);
singleGuessHandler.runSingleGuess(8, 65);
InOrder inOrder = inOrder(scanner, printStream);
inOrder.verify(printStream).println(" guess 8:");
inOrder.verify(scanner).nextInt();
inOrder.verify(printStream).println("Correct answer after only 8 guesses – Excellent!");
inOrder.verifyNoMoreInteractions();
}
}
请注意,课程MyScanner
和Main
未经过测试。测试它们需要使用真实的java.util.Scanner
和真实的System.out
打印流。这是一种验收测试(一切都是真实的,没有假货或模拟),在这种情况下,最好通过将java应用程序作为单独的进程运行并为其提供数字并检查它输出的内容来实现。
测试猜测数字的范围是个好主意。我会通过将new Random().nextInt(100)
提取到类中来完成此操作,例如RandomNumberProvider
。然后剩下的就是:
Game
Game
的{{1}}测试Game
传递给SingleGuessHandler
返回的提供商RandomNumberProvider
添加测试 - 属性测试或模拟Random
另请注意,当不同的测试调用相同的方法时,会使用不同的值。它可以防止在实现中对这些值进行意外硬编码。
答案 1 :(得分:2)
提取一个捕获代码逻辑的“纯函数”,然后测试将是微不足道的。
static String reply(int guess, int number, int guessCount) {
return guess > number ? "Clue: lower"
: guess < number ? "Clue: Higher"
: "Correct answer after only " + guessCount + " guesses -- Excellent!";
}
答案 2 :(得分:0)
提取功能guess()
并传递guess
和number
。让它返回结果字符串或表示它的抽象值。
将函数和计数器封装在新类中。每次guess()
,递增它。当你达到10次猜测时禁用猜测。
现在您可以控制代码的输入和输出,并且可以正确测试它,而不必依赖副作用(控制台输入/输出)。
答案 3 :(得分:0)
你只需要写三个不同的断言来满足不同的条件。你还需要把它放在某种功能中。我从来没有尝试对主函数进行单元测试,但我猜你可以这样做,但通常是在函数中返回一些值。我不确定你将如何测试print语句。也许您可以将文本放在变量中然后打印出来。它看起来像这样。
public string gameFunction(int guess){
String printVariable;
for (int i=1; i<=10; i++){ // for loop from 1 to 10
System.out.println(" guess "+i+ ":");
int guess = scan.nextInt();
//if guess is greater than number entered
if(guess>number)
printVariable = "Clue: lower";
System.out.println("Clue: lower");
//if guess is less than number entered
else if (guess<number )
printVariable = "Clue: Higher";
System.out.println("Clue: Higher");
//if guess is equal than number entered
else if(guess==number) {
printVariable = "Correct answer after only "+ i + " guesses – Excellent!";
System.out.println("Correct answer after only "+ i + " guesses – Excellent!");
return printVariable;
}
}
@Test
public void testDiscreteize(){
int guess = 1
int number = 2
String testPrint = "Clue: lower";
String returnValue = game function(guess);
assertEquals(testPrint, returnValue);
}
请注意,我还没有对这些代码进行测试,这只是关于如何设置的一般概念。