How to JUnit test for any output in Java - java

I'd like to test the two methods below, but because its based on random output my go-to assertEquals() won't work.
I just want to test to ensure the methods are producing some kind of output. Any ideas?
Novice programmer, appreciate the help.
public void compRandomChoice() {
double choice = (Math.random() * 100 / 100);
if (choice > 0 && choice <= 0.34) {
computer.setChoice(HandThrow.ROCK);
} else if (choice > 0.34 && choice <= 0.67) {
computer.setChoice(HandThrow.PAPER);
} else {
computer.setChoice(HandThrow.SCISSORS);
}
}
public String gameWinner() {
String gameResult;
if (human.getChoice() == computer.getChoice()) {
gameResult = "ITS A TIE!";
} else if (human.getChoice() == HandThrow.ROCK
&& computer.getChoice() == HandThrow.SCISSORS
|| human.getChoice() == HandThrow.PAPER
&& computer.getChoice() == HandThrow.ROCK
|| human.getChoice() == HandThrow.SCISSORS
&& computer.getChoice() == HandThrow.PAPER) {
gameResult = "CONGRATS, YOU WIN!";
} else {
gameResult = "COMPUTER WINS!";
}
return gameResult;
}

I suggest changing compRandomChoice() function as follows
public void compRandomChoice(double rand_no) {
double choice = (rand_no * 100 / 100);
if (choice > 0 && choice <= 0.34) {
computer.setChoice(HandThrow.ROCK);
} else if (choice > 0.34 && choice <= 0.67) {
computer.setChoice(HandThrow.PAPER);
} else {
computer.setChoice(HandThrow.SCISSORS);
}
}
Then in your program, you can call it as compRandomChoice(Math.random()) Now in your Unit Tests,
you can hard-code the input, e.g. compRandomChoice(0.5) and assert that the result is as expected.
Similarly, change public String gameWinner() as public String gameWinner(String human_choice, String computer_choice)
public String gameWinner(String human_choice, String computer_choice) {
String gameResult;
if (human_choice == computer_choice) {
gameResult = "ITS A TIE!";
.......
In your code, you can call the function as gameWinner(human.getChoice(), computer.getChoice()). In your Unit Tests, you can hard code the input (using an approach similar to used for previous function) and assert that you get expected result based on the parameter you are passing.

What you are discovering is that you want to test (assert) that your code behaves correctly given certain inputs, but that you can not easily control the inputs in question as your code is written. Congratulations! You have discovered (one of) the virtues of test-driven development.
The solution is to re-structure your code in a way that makes it easier to test the properties you care about.
What property do you care about for the compRandomChoice function? Perhaps that it produces an output that is evenly distributed across the three choices. To do that, you might imagine writing a short test that iterates over many calls to compRandomChoice and does some simple analysis (and the Law of Large Numbers) to show that you get each choice about a third of the time.
How about for the gameWinner function? There you want to try different combinations of inputs and verify that the correct winner is determined. The inputs to the algorithm are the choices made by the computer and the human. So to test it, you must be able to manufacture human and computer choices and provide them to the algorithm. This would typically be done by using dependency injection...that is providing the objects that your algorithm depends on in the constructor or as a parameter instead of hard-coding them.
For example, the simplest thing to do would be to pass the choices into the gameWinner function and have it return a the winner (e.g., as an enum):
enum Result { PLAYER1, PLAYER2, TIE }
/**
* Determine the game winner.
* #param player1_choice
* #param player2_choice
* #return PLAYER1 .
*/
public Result gameWinner(HandThrow player1_choice, HandThrow player2_choice) {
if (player1_choice.equals(player2_choice)) { return TIE }
...
}
Then the tests are easy to write:
#Test
public void paperBeatsRock() {
assertEquals(gameWinner(HandThrow.ROCK, HandThrow.PAPER), PLAYER2);
}
Take a look at Writing Testable Code; it gives a lot of hints on how to do what you want to do successfully.

I would extract getting random into a package private method
double getRandomChoice() {
return (Math.random() * 100 / 100);
}
so that in the test I could override it
MyClass mc = new MyClass() {
#Override
double getRandomChoice() {
return 2.0;
}
};

For my needs and time available I found the assertNotNull() test method, and used that.
#Test
public void testGameWinner() {
assertNotNull(testLogic.gameWinner());

Related

How to break loop at some point of iteration and check what system printed out?

I am trying to find out how can I check what system printed out at some point of iteration during the while loop statement.
I have this method:
/**
* This method counts how much money user inserted
* If it is not enough to buy chosen cup size it asks user to insert more
* Otherwise it checks if user does not need the change
* and collects money to machine based on cup size price
* This method gets the message from properties file by key identifies
* add.more.money - if not enough money is in machine
* user.paid.change - if user put too much to machine
* user.paid - if user paid the exact amount of money
* #param constantPrice - cup size price
* #return countMoney - how much user put to machine
*/
#Override
public String countMoneyForCupSize(double constantPrice) {
// constant - price depending on cup size
String countMoney = " ";
double sessionMoney = 0;
boolean flag = true;
while(flag) {
if(constantPrice > sessionMoney) {
System.out.println(MessageFormat.format(prop.getProperty("add.more.money"), (constantPrice-sessionMoney)));
double insertedCash;
try {
insertedCash = insertCash();
sessionMoney = sessionMoney + insertedCash;
if(insertedCash == 0) {
System.out.println(MessageFormat.format(prop.getProperty("end.procedure"), sessionMoney));
flag = false;
}
} catch (InvalidCoinException e) {
System.out.println(e.getMessage());
}
}
else {
double change = sessionMoney - constantPrice;
String makeCoffeeText = makeCoffee();
if(change > 0) {
countMoney = MessageFormat.format(prop.getProperty("user.paid.change"), makeCoffeeText, sessionMoney, change);
}
else {
countMoney = MessageFormat.format(prop.getProperty("user.paid"), makeCoffeeText, sessionMoney);
}
collectMoney(constantPrice);
flag = false;
}
}
return countMoney;
}
JUnit:
#org.junit.Rule
public final ProvideSystemProperty property1 = new ProvideSystemProperty("MoreEuro", "You need more: 0.5 euro");
#org.junit.Test
public void testCountMoneyForCupSize() {
System.out.println("---------------- Count Money For Cup Size -----------------");
double largePrice = 1.5;
double mediumPrice = 1;
double smallPrice = 0.75;
try {
when(machineSpy.insertCash()).thenReturn(1.0);
assertEquals(machineSpy.countMoneyForCupSize(largePrice), System.getProperty("MoreEuro"));
} catch (InvalidCoinException e) {
System.out.println(e.getMessage());
}
}
So I want to be clear that If user inserted 1 euro he still needs to insert half a euro more.
1) when(machineSpy.insertCash()).thenReturn(1.0);
Mocking private method invocation called by the tested public method is not necessarily a good thing as you should mock dependency and not the behavior of the object under test. If insertCash() has some specificities that have to be mocked, you should probably move out in another class.
2) About :
how to break loop at some point of iteration and check what system
printed out
Why not just executing a break instruction ?
3) machineSpy.countMoneyForCupSize(largePrice);
So I want to be clear that If user inserted 1 euro. He still need to
insert half euro more
Rather than trying to test the output written in the console that is not really testing the method behavior, I think that you should change the contract of countMoneyForCupSize(double).
In your actual version the method returns a formatted String. It should not.
Logic and rendering tasks are two distinct things.
Mixing both responsibilities violates the Single Responsibility principle (more than one reason to change a class).
Besides, it may prevent from testing the core logic of the method as in your case
Here :
if(change > 0) {
countMoney = MessageFormat.format(prop.getProperty("user.paid.change"), makeCoffeeText, sessionMoney, change);
}
else {
countMoney = MessageFormat.format(prop.getProperty("user.paid"), makeCoffeeText, sessionMoney);
}
You should rather create an instance of a custom class that contains all these data and return it rather than a String.
For example :
....
CountMoney countMoney = null;
...
if(change > 0) {
countMoney = new CountMoney(makeCoffeeText, sessionMoney, change);
}
else {
countMoney = new CountMoney(makeCoffeeText, sessionMoney);
}
...
return countMoney;
In your applicative code that invokes CountMoney countMoneyForCupSize() you could then call a rendered method (located in a rendering class) that performs the rendering, for example : String renderingCountMoney(CountMoney countMoney).
In this way your design would be better (each class and each method has well defined responsibilities) and you can unit test countMoneyForCupSize() without considerations about user text rendering.
You can check directly that insertCash was called multiple times. One way to do this is to to mock multiple calls to insertCash with thenReturn:
when(machineSpy.insertCash()).thenReturn(1.0, 0.5);
After that you can verify that insertCash was called exactly two times:
verify(machineSpy, times(2)).insertCash();
verifyNoMoreInteractions(machineSpy);
Check out this question for other options:
Using Mockito with multiple calls to the same method with the same arguments
If you still want to capture and test the output to System.out then you need to redirect standard output. This was already covered in earlier questions:
Redirect System.out.println
JUnit test for System.out.println()

Change the value of a variable each time another variable changes

I am currently making a text adventure game in Java, but I have come across a problem:
I need the value of a String variable to change each time the value of a particular int variable changes.
I want the program to perform this task (then continue where it left off) each time the value of an int variable changes:
if (enemyposition == 1) {
enemyp = "in front of you";
}
else if (enemyposition == 2) {
enemyp = "behind you";
}
else if (enemyposition == 3) {
enemyp = "to your left";
}
else if (enemyposition == 4) {
enemyp = "to your right";
}
else {
enemyp = "WOAH";
}
Thanks! :D
You could make the code much shorter using an array.
String[] message = {"WOAH", // 0
"in front of you", // 1
"behind you", // 2
"to your left", // 3
"to your right"}; // 4
enemyp = (enemyposition > 0 && enemyposition < 5) ? message[enemyposition] :
message[0];
The question you're asking sounds like it might be answerable by creating a class to hold the enemyposition integer. Add a "setter" method to your class to set the integer. You can write your setter method so that when the integer is set, it also sets up a string. Then write a "getter" method to retrieve the string. That's one common way of making sure two variables change together.
public class EnemyPosition {
private int enemyposition;
private String enemyp;
public void setPosition(int n) {
enemyposition = n;
enemyp = [adapt your code to set this based on the position]
}
public String getEnemyp() {
return enemyp;
}
}
I'm sure there are a lot of details missing, but you get the idea. Then instead of int enemyposition in the rest of your code, use EnemyPosition enemyposition = new EnemyPosition(), and use the setPosition method instead of assigning to it.
That's not the only solution (an array or Map that maps integers to strings may be good enough), but it's one OOP way to do things.

randomly generated numbers game with probability and loops

In the land of Puzzlevania, Aaron, Bob, and Charlie had an argument over which
one of them was the greatest puzzler of all time.
To end the argument once and
for all, they agreed on a duel to the death.
Aaron was a poor shooter and only hit
his target with a probability of 1>3.
Bob was a bit better and hit his target with a
probability of 1>2.
Charlie was an expert marksman and never missed. A hit means
a kill and the person hit drops out of the duel.
To compensate for the inequities in their marksmanship skills, the three decided
that they would fire in turns, starting with Aaron, followed by Bob, and then by
Charlie. The cycle would repeat until there was one man standing, and that man
would be the Greatest Puzzler of All Time.
An obvious and reasonable strategy is for each man to shoot at the most accurate
shooter still alive, on the grounds that this shooter is the deadliest and has the best
chance of hitting back.Write a program to simulate the duel using this strategy.
Your program should use
random numbers and the probabilities given in the problem to determine whether
a shooter hits the target.
Create a class named Duelist that contains the dueler’s
name and shooting accuracy, a Boolean indicating whether the dueler is still alive,
and a method ShootAtTarget ( Duelist target ) that sets the target to dead if
the dueler hits his target (using a random number and the shooting accuracy) and
does nothing otherwise.
Once you can simulate a single duel, add a loop to your program that simulates
10,000 duels. Count the number of times that each contestant wins and print the
probability of winning for each contestant (e.g., for Aaron your program might
output “Aaron won 3,595>10,000 duels or 35.95%”).
An alternate strategy is for Aaron to intentionally miss on his first shot. Modify the
program to accommodate this new strategy and output the probability of winning
for each contestant.
Which strategy is better for Aaron: to intentionally miss on the
first shot or to try and hit the best shooter? Who has the best chance of winning,
the best shooter or the worst shooter?
Ok so that the problem. Here is my code so far:
public class Duelist {
private String name;
private double probabilityOfHitting;
private boolean alive = true;
//Only declared instance variables. Must created setters and getters
public void setName(String newName){
name = newName;
}
//name setter created
public void setProbabilityOfHitting( double newProbabilityOfHitting){
probabilityOfHitting = newProbabilityOfHitting;
}
//probability of hitting setter created
public void setAlive(boolean newAlive){
alive = newAlive;
}
//name setter created
//now must create getters
public String getName(){
return name;
}
//created the name getter
public double getProbabilityOfHitting(){
return probabilityOfHitting;
}
//created the probability of hitting getter
public boolean getAlive(){
return alive;
}
//created the alive getter
//no constructors created before
public Duelist(String tempName, double tempProbability){
name = tempName;
probabilityOfHitting = tempProbability;
}
//constructor is now created
//need to create a method for the duelists to shoot at each other
public void shootAtTarget(Duelist target){
double randomNum = Math.random();
if (this.probabilityOfHitting ==1){
target.setAlive(false);
target.getAlive();
}
else if (randomNum <= this.probabilityOfHitting){
target.setAlive(false);
target.getAlive();
}
else {
target.getAlive();
}
}
}
public class Tester {
public static void main(String[] args) {
int winsA = 0;
int winsB = 0;
int winsC = 0;
Duelist aaron = new Duelist("Aaron",(1/3));
Duelist bob = new Duelist("Bob", (1/2));
Duelist charlie = new Duelist("Charlie", 1);
if(aaron.getAlive() == true){
if(charlie.getAlive()== true){
aaron.shootAtTarget(charlie);
}
else if(bob.getAlive() == true){
aaron.shootAtTarget(bob);
}
else{
winsA++;
}
}
else if(bob.getAlive() == true){
if(charlie.getAlive() == true){
bob.shootAtTarget(charlie);
}
else if(aaron.getAlive() == true){
bob.shootAtTarget(aaron);
}
else{
winsB++;
}
}
else{
if (bob.getAlive() == true){
charlie.shootAtTarget(bob);
}
else if(aaron.getAlive() == true){
charlie.shootAtTarget(aaron);
}
else{
winsC++;
}
}
System.out.println(winsA);
System.out.println(winsB);
System.out.println(winsC);
}
}
I know I haven't gotten close to finishing the problem yet. What I did in my tester class was to try and simulate one duel and once when I simulated one duel, I would be able to loop it so I can simulate more. The problem I'm having is that the when I run the code, the wins for Aaron, Bob, and Charlie all come up to 0 and I don't know why.
As the last parameter in the constructor calls, you wrote
Duelist aaron = new Duelist("Aaron",(1/3));
There you are dividing an int by another int, and the result will be 0 in this case. This has to be changed to
Duelist aaron = new Duelist("Aaron",(1.0/3.0));
so that double values are used (and the result will be 0.3333, as desired).
Most of your Duelist class does not seem to be "wrong", but the shootAtTarget method could be improved.
A general hint: I'd recommend you to never use Math.random(). This will deliver unpredictable results. Instead, you should use an instance of java.util.Random. This can be initialized with a certain random seed, so that it always provides the same sequence of random numbers. This makes debugging much easier.
Additonally, some tests have been redundant. When the probabilityOfHitting is 1.0, then there is no special test required: The random number will always be less-than-or-equal to 1.0. You are also occasionally calling target.getAlive() for no apparent reason.
So in the end, the method could look like this:
private static Random random = new Random(0);
//need to create a method for the duelists to shoot at each other
public void shootAtTarget(Duelist target)
{
double randomNum = random.nextDouble();
if (randomNum <= this.probabilityOfHitting)
{
target.setAlive(false);
}
}
However, the main problem was in your Test class. I'm not sure about general recommendations here. One could go very far in terms of abstraction. (A Java Enterprise Architect would probably end up with writing a AbstractDuelistStrategyFactory somewhere...). But to put it simply: At the moment, you are doing at most one shot. After one shot, nobody can have won. And you don't know how many shots have to be taken before there is only one duelist remaining.
Much of this could be made more elegant and flexible if you placed the Duelists into a List<Duelist>. But without that, an approach that is "structurally close to what you started" could look like this:
int alive = 3;
while (alive > 1)
{
System.out.println("Status: A:"+aaron.getAlive()+" B:"+bob.getAlive()+" C:"+charlie.getAlive());
if (aaron.getAlive())
{
if(charlie.getAlive())
{
System.out.println("A shoots at C");
aaron.shootAtTarget(charlie);
if (!charlie.getAlive())
{
System.out.println("A killed C");
alive--;
}
}
else if(bob.getAlive())
{
System.out.println("A shoots at B");
aaron.shootAtTarget(bob);
if (!bob.getAlive())
{
System.out.println("A killed B");
alive--;
}
}
}
// Other cases ...
}
if (aaron.getAlive())
{
winsA++;
}
if (bob.getAlive())
{
winsB++;
}
if (charlie.getAlive())
{
winsC++;
}
(Note that there are still cases missing!)

I can't figure out why this Recursion isn't working

I am learning about Recursions, and I haven't fully grasped it yet. So here I am trying to do an assignment on recursion but I'm stuck.
In this assignment, I am supposed to ask the user to input phrases, and the program determines whether it's a palindrome or not. We are supposed to accomplish this task using recursions.
This is the section with the recursion, and I can't quite figure out how to tackle it, as when I run it, I get no error, but it always comes up as false.
I'm using a ArrayList to keep all the user input.
Here's the code I've got right now
//instance variables
private boolean det;
private String input;
private String inputHelp;
//constructor
public RecursivePalindrome(String i)
{
det = false;
input = i;
inputHelp = "";
}
//determines if the method is a palindrome or not using recursions
public boolean palindrome(String b)
{
if(inputHelp.length() == 0)
{
det = true;
}
if(inputHelp.substring( 0 , 1 ).equals(inputHelp.substring( inputHelp.length() )))
{
inputHelp = inputHelp.substring( 1, inputHelp.length());
palindrome(inputHelp);
}
else
{
det = false;
}
return det;
}
There are three mistakes. First, note the substring documentation: second parameter is the end index "exlusive". Secondly, you need to use the result of the recursive call. And finally (as pointed out correctly by ajb in the comments), you should account for palindromes with odd letter count (first condition):
if (inputHelp.length() <= 1)
{
det = true;
}
else if (inputHelp.substring(0, 1)
.equals(inputHelp.substring(inputHelp.length() - 1)))
{
inputHelp = inputHelp.substring( 1, inputHelp.length() - 1);
det = palindrome(inputHelp);
}
else
{
det = false;
}
Also, you can make it a bit more readable:
public boolean palindrome(String b)
{
if (b.length() <= 1)
{
return true;
}
if (b.substring(0, 1)
.equals(b.substring(b.length() - 1)))
{
return palindrome(b.substring(1, b.length() - 1));
}
return false;
}
Further improvements can be made - lines still seem to long, especially the second condition (left as an exercise for the reader ;)).
As far as I can tell you are never setting inputHelp to anything other than an empty string, and the string b which is passed in to your method is not used anywhere.
So the method will never call back on to itself, and even if it did the value passed in would not be used for anything, rendering the recursion useless.

Java Palindrome, methods, and abstract classes?

I'm stuck on an assignment, largely due to an extreme lack of examples or even relevant diagrams from my textbook and class material.
The reason I structured the program the way I did is because I'm required to use 4 methods: a main method that executes all the other methods, a retrieve input method, a check method, and a display method. I love to hear about best practices, but I'm forced to code like this.
My main problem is the abstract classes I have. Any variables I write in one method won't be resolvable in another, I don't know how to make the variables global.
secondly, the code does not compile, the example I've found doesn't have a classic main, i don't really know how to make main implement methods, or make the compiler happy with abstraction.
also no clue on how to take my boolean result and use that to display the results in the display method. yes its asinine, I'd rather just do it in the check method.
all i know for sue is that my "logic" so far works. i think. any help to point me in the right direction would be very much appreciated. if thee is a way to do this without abstract classes i'd love to hear it, i think the abstraction is unnecessary.
well here's my monster so far:
import javax.swing.JOptionPane;
interface Palindrome {
void retrieveInput(String[] args);
boolean Check(String s);
void display();
}
abstract class Sub_Palindrome implements Palindrome {
public void retrieveInput(String[] args)
{
String Uinput;
int number1;
int digit1; // first digit
int digit2; // second digit
int digit3;
int digit4; // fourth digit
int digit5; // fifth digit
Uinput = JOptionPane.showInputDialog("Enter A 5 Digit Integer");
try { //Sanitize user input, make sure input entered is a number
number1 = Integer.parseInt(Uinput);
} catch (NumberFormatException String) {
JOptionPane.showMessageDialog(null, "Input invalid, please enter an integer",
"///-D-A-T-A---E-R-R-O-R-\\\\\\", JOptionPane.ERROR_MESSAGE);
return;
}
if (number1 < 10000 || number1 > 99999) { //Sanitize user input, make sure the given number is between 10000 and 99999
JOptionPane.showMessageDialog(null,
"The number entered must be between 10000 and 99999",
"///-D-A-T-A---E-R-R-O-R-\\\\\\", JOptionPane.ERROR_MESSAGE);
return;
}
}
public boolean Check(String s)
{
digit1 = number / 10000;
digit2 = number / 1000 % 10;
digit3 = number % 1000 / 100 % 10; // is the third digit even necessary?
digit4 = number % 10000 % 1000 % 100 / 10;
digit5 = number % 10000 % 1000 % 100 % 10;
if (digit1 == digit5 && digit2 == digit4)
return true;
else
return false;
}
public void display()
{
//display output text based upon result from IsPalinDrome
//after displaying result, start from the beginning and ask user to input data again
}
}
Move the variables outside methods and put directly in class scope
Writing main method is the first thing you learn in java. Look into your tutorial again
You can use a boolean variable boolean displayCheck = false; and set the same
And one question from my side: If your code doesn't compile what makes you feel that the logic is correct?

Categories