Simple Junit testing with OOP java - java

Below is a class that represents time using hours and minutes (seconds are not represented).
public class ClassTime {
public static int hour;
public static int minute;
public static String amPm;
//Initializes the object using specified parameter values.
public ClassTime(int hour, int minute, String amPm){
//hour value between 1 and 12, both inclusive.
boolean validHour = false;
if (hour >= 1 && hour <= 12){
validHour = true;
this.hour = hour;
} else {
throw new IllegalArgumentException("Invalid hour value");
}
//minute value between 0 and 59, both inclusive.
boolean validMinute = false;
if (minute >= 0 && minute <= 59){
validMinute = true;
this.minute = minute;
} else {
throw new IllegalArgumentException("Invalid minutes value");
}
//amPm is either "am" or "pm".
if (amPm.equalsIgnoreCase("am")){
this.amPm = amPm;
} else if (amPm.equalsIgnoreCase("pm")){
this.amPm = amPm;
} else {
throw new IllegalArgumentException("Invalid am/pm value");
}
}
/*
* Returns a string using the format "hour:minutes am" or "hour:minutes pm".
* A single space is used in between minutes and am/pm. The minutes always
* appear with two digits (e.g., 0 minutes will be "00").
*/
public String toString(){
String toBeReturned = "hour:" + String.format("%02d", this.minute) +
" " + amPm;
return toBeReturned;
}
/*
* Compares two time objects. Two time objects are considered equal if
* they represent the same time.
*/
public boolean equals(ClassTime obj){
boolean equal = false;
if (obj.minute == this.minute && obj.hour == this.hour &&
obj.amPm.equalsIgnoreCase(this.amPm)){
equal = true;
}
return equal;
}
/*
* Compares two time objects. Returns -1 if the current object is a time
* that precedes the time parameter, 0 if the current object and the time
* parameter represent the same time, and 1 if the current object represents
* a time that is after the time parameter.
*/
public int compareTo(ClassTime obj){
int returnNum = 2;
if(this.amPm.equalsIgnoreCase("am") && obj.amPm.equalsIgnoreCase("pm")){
returnNum = -1;
} else if (this.amPm.equalsIgnoreCase("pm") &&
obj.amPm.equalsIgnoreCase("am")){
returnNum = 1;
} else if (this.amPm.equalsIgnoreCase(obj.amPm)){
if (this.hour < obj.hour){
returnNum = -1;
} else if (this.hour > obj.hour){
returnNum = 1;
} else if (this.hour == obj.hour){
if (this.minute < obj.minute){
returnNum = -1;
} else if (this.minute > obj.minute){
returnNum = 1;
} else if (this.minute == obj.minute){
returnNum = 0;
}
}
}
return returnNum;
}
/*
* Returns a new time object corresponding to the time we will have after
* increasing the time parameter by the specified number of minutes.
*/
public static ClassTime increaseByMinutes(ClassTime obj, int minutes){
//create variables that monitor changes in minutes, hours, and amPm.
int minValue = obj.minute + minutes;
int hourValue = obj.hour;
String amPmValue = obj.amPm;
/*
* increments hour and minutes if the total minutes is below two hours,
* but greater tan or equal to 1 hour.
*/
if(minValue > 59 && minValue < 120){
minValue = minValue % 60;
hourValue = hourValue + 1;
if (hourValue > 12){
hourValue = hourValue % 12;
} else if(hourValue == 12 && amPmValue.equalsIgnoreCase("am")){
amPmValue = "pm";
} else if (hourValue == 12 && amPmValue.equalsIgnoreCase("pm")){
amPmValue = "am";
}
/*
* Increment for when the total amount of minutes is greater
* or equal to 2 hours.
*/
} else if (minValue > 119){
for(int i = 0; i <= (minValue/60); i++){
hourValue++;
if(hourValue > 12){
hourValue = hourValue % 12;
} else if (hourValue == 12 && amPmValue.equalsIgnoreCase("am")){
amPmValue = "pm";
} else if (hourValue == 12 && amPmValue.equalsIgnoreCase("pm")){
amPmValue = "am";
}
}
}
/*
* Create a new ClassTime object with the found values of minutes, hours,
* and amPm Value. This is what will be returned.
*/
ClassTime newObject = new ClassTime(hour, minute, amPm);
newObject.minute = minValue;
newObject.hour = hourValue;
newObject.amPm = amPmValue;
return newObject;
}
public static void main(String[] args) {
}
}
I don't know how to test the constructor or the methods in a JUnit test case. So far the only thing I can come up with for the constructor is:
import static org.junit.Assert.*;
import org.junit.Test;
public class JunitTests {
#Test
public void testClassTime() {
ClassTime object1 = new ClassTime(3, 30, "pm");
}
}
How would I finish doing a test for the constructor and maybe just 1 method. Please don't do all of them.

I suggest you read up on unit testing, your question is a bit too broad.
Basically the idea is that given some situation, when a thing happens, then some conditions should be true. (I personally add comments to my tests to help me think in those terms.)
Here's an abstract example:
Given bread and a toaster
When I put the bread in the toaster and get it out when it's done
Then it should be toasted
Look up JUnit's assertion library to help find good ways to assert conditions. When looking up JUnit examples you'll usually see things like assertTrue(...) or assertNotNull(...), these are static methods from the Assert class, I mention this because you seem like a novice and I don't want you to get confused by examples. Usually all these methods are imported statically in the examples.
What you have in your test case currently is the given, a when could be doing toString() (String actual = object1.toString();). Your then clause would be asserting that the String returned equals what it should, which is probably "3:30 PM" (assertEquals("3:30 PM", actual);). I didn't design your code, so I don't know if that's correct, you may expect it to return `"Hello, World!" In any case, I'd run this one first ;)

Related

how to insert a date-time hh: mm into an array list sorted by times only if the time is 10 min before or after the insertion point

I have one question for my first development project in Java9.
I need to insert an Object with some info and a Date type, inside an ArrayList
only if the time is not present in the ArrayList and if it respects the condition that every time in the ArrayList must be stored every 10 minutes.
So, for example the idea is something like that:
correct: [21:10, 21:20, 21:50, 22:00],
incorrect: [21:05, 21:10, 21:20, 21:55, 22:00]
I try something like this:
private static ArrayList<Order> orders = new ArrayList<Order>();
//ordinazione = orderTime,name,surname,adderess,pizze;
public Pizzeria() {
Order ord = new Order(name, surname, address, num_pizze);
isValid(ord);
}
private void isValid(Order ord) {
boolean valid = false;
long prew,current;
long add = ord.getOrderTime().getTime();
int min10 = 10*60*1000; //10 minutes
if(orders.size() == 0) {
addOrder(ord);
}else if(orders.size() == 1){
current = orders.get(0).getOrderTime().getTime() / 1000;
if(add > current) {
if(add - current >= min10) {
valid = true;
addOrder(order);
}
}else{
if(current - add >= min10) {
valid = true;
addOrder(ord);
}
}
}else{
int i = 0;
while (orders.size() > i) {
prec = i > 1 ? orders.get(i-1).getOrderTime().getTime() / 1000 : 0;
current = orders.get(i).getOrderTime().getTime() / 1000;
if (current - add >= min10 && add - prec >= min10) {
valid = true;
addOrder(ord);
break;
}
i++;
}
}
if(!valid) {
System.out.println("this time is not allowed!");
}
}
public void addOrder(Orderd ord) {
orders.add(ord);
}
any advice?
It may not be the most beautiful solution, but it’s pretty simple: allocate an array with a slot for an order every 10 minutes of the day.
First we need the array of orders:
/** Accept an order every 10 minutes */
private static final int SLOT_SIZE_MINUTES = 10;
private Order[] orders
= new Order[Math.toIntExact(Duration.ofDays(1).toMinutes()) / SLOT_SIZE_MINUTES];
Now the method to fit a new order into the orders could be like:
/**
* If the order fits into a vacant slot that agrees with the time +/- 10 minutes,
* adds it there, adjusts the order time and returns true;
* otherwise returns false
*/
private boolean addOrderIfValid(Order newOrder) {
LocalTime orderTime = newOrder.getOrderTime();
int slotIndex = orderTime.get(ChronoField.MINUTE_OF_DAY) / SLOT_SIZE_MINUTES;
if (orders[slotIndex] != null) { // slot is already taken
slotIndex++;
if (slotIndex == orders.length) { // end of array
// start over from 00:00
slotIndex = 0;
}
}
if (orders[slotIndex] == null) { // vacant
newOrder.setOrderTime(LocalTime.MIN.with(ChronoField.MINUTE_OF_DAY, slotIndex * SLOT_SIZE_MINUTES));
orders[slotIndex] = newOrder;
return true;
} else { // did not find a vacant slot
return false;
}
}
What my method does: It tries to fit the order into the right 10 minutes slot based on the order time already in the order, truncating the time to a 10 minutes slot. If the slot is already taken, it looks into the following slot, using cyclic overflow. If either of the two slots tried is vacant, it sets the order time to the appropriate time for the slot found. This is also what ensures that the time will be at a whole 10 minutes of the hour: 21:00, 21:10, etc., not 21:05.
Link
Oracle tutorial: Date Time explaining how to use java.time.

Converting String time format of HH:MM:SS (AM/PM) into Seconds

So I have this assignment that is asking us to take in a String format of time in the order of HH:MM:SSAM or HH:SS:MMPM. The constraint is that it cannot run if it is in wrong format, let it be missing any form of the AM or PM, missing a number, or if it is in 24 Hour Format.
I have the whole idea down, however for my statements, it is giving me the error of:
bad operand types for binary operator '>'
incomparable types: String and int
Did I convert them improperly or am I doing something else wrong?
public static void main(String args[]) {
//Test Methods
String fullTime1 = "03:21:36AM";
secondsAfterMidnight(fullTime1);
}
public static int secondsAfterMidnight(String time) {
String[] units = time.split(":");
int hours = Integer.parseInt(units[0]);
int minutes = Integer.parseInt(units[1]);
int seconds = Integer.parseInt(units[2]);
int totalSeconds = 0;
if (units[0] > 12 || units[1] > 59 || units[2] > 59) { //1st Error applies to these three, units[0] > 12 units[1] > 59 units[2] > 59
return -1;
} else if (time.equalsIgnoreCase("AM") || time.equalsIgnoreCase("PM")) {
totalSeconds = (hours * 3600) + (minutes * 60) + (seconds);
} else if (time.equalsIgnoreCase("AM") && units[0] == 12) { //2nd Error applies to this units[0] == 12
totalSeconds = (minutes * 60) + (seconds);
} else {
return -1;
}
return totalSeconds;
}
You have already parsed the String values and saved them in the variables hours , minutes, seconds. Then you can use those for the check in the if.
Also the presence of AM?PM in the Integer.parseInt() will cause NumberFormatException to avoid it remove the String part from the number by using regex.
Also for checking the presence of AM/PM you can use String.contains.
Please check the reformatted code below:
public static int secondsAfterMidnight(String time) {
String[] units = time.split(":");
int hours = Integer.parseInt(units[0]);
int minutes = Integer.parseInt(units[1]);
int seconds = Integer.parseInt(units[2].replaceAll("[^0-9]", ""));
int totalSeconds = 0;
if (hours > 12 || minutes > 59 || seconds > 59) {
return -1;
} else if (time.contains("AM") || time.contains("PM")) {
totalSeconds = (hours * 3600) + (minutes * 60) + (seconds);
} else if (time.contains("AM") && hours == 12) {
totalSeconds = (minutes * 60) + (seconds);
} else {
return -1;
}
return totalSeconds;
}
Please note that even though you have converted the String to int, you are still comparing String with int. There would also be a RuntimeException when you do this:
int seconds = Integer.parseInt(units[2]);
As units[2] will contain 36AM. So you should be using substring() to remove the "AM/PM" part.
units is of type String and you are trying to compare it with an int hence the compile time error.
You need to convert the String to an int and then compare it, as shown below :
Integer.parseInt(units[0]) > 12
so on and so forth.
Also rather than re-inventing the wheel, you can make use of the already existing java-8's LocalTime to find the number of seconds for a particular time:
public static int secondsAfterMidnight(String time) {
LocalTime localTime = LocalTime.parse(time, DateTimeFormatter.ofPattern("hh:mm:ss a"));
return localTime.toSecondOfDay();
}
I haven't verified your logic to calculate the seconds, but this code has corrections:
public static int secondsAfterMidnight(String time) {
String[] units = time.split(":");
int hours = Integer.parseInt(units[0]);
int minutes = Integer.parseInt(units[1]);
int seconds = 0;
String amPm = "";
if ( units[2].contains("AM") || units[2].contains("PM") ||
units[2].contains("am") || units[2].contains("pm") ) {
seconds = Integer.parseInt(units[2].substring(0, 2));
amPm = units[2].substring(2);
}
else {
seconds = Integer.parseInt(units[2]);
}
int totalSeconds = 0;
if (hours > 12 || minutes > 59 || seconds > 59) {
return -1;
} else if (amPm.equalsIgnoreCase("AM") || amPm.equalsIgnoreCase("PM")) {
totalSeconds = (hours * 3600) + (minutes * 60) + (seconds);
} else if (amPm.equalsIgnoreCase("AM") && hours == 12) {
totalSeconds = (minutes * 60) + (seconds);
} else {
return -1;
}
return totalSeconds;
}
java.time
static DateTimeFormatter timeFormatter
= DateTimeFormatter.ofPattern("HH:mm:ssa", Locale.ENGLISH);
public static int secondsAfterMidnight(String time) {
try {
return LocalTime.parse(time, timeFormatter).get(ChronoField.SECOND_OF_DAY);
} catch (DateTimeParseException dtpe) {
return -1;
}
}
Let’s try it out using the test code from your question:
String fullTime1 = "03:21:36AM";
System.out.println(secondsAfterMidnight(fullTime1));
12096
This is the recommended way for production code.
Only if you are doing an exercise training string manipulation, you should use one of the other answers.
Link: Oracle tutorial: Date Time explaining how to use java.time.

Java Clock Program

I am trying to make a clock program using Java, and I got everything to work properly except I cannot get the program to change the negative values to 0. I also cannot get the program to set the values of hours, minutes, and seconds to 0 if they are out of range. I have a tester program that I have to use and the T1 and T2 clock values are incorrect in my code. T1 should be 0:0:0 and T2 should be 0:0:0 as well. However, when I output my code it comes out as T1 being -3:-21:-30 and T2 is 24:60:60. I know there is something wrong with my code, but I can't find the issue, if anyone would be able to help me that would be greatly appreciated. Below is my code and then the second section is the tester code that I have to use.
public class Clock
{
// instance variables
private int hours;
private int minutes;
private int seconds;
public void setHours(int newHours) {
hours = newHours;
if (hours<0 || hours > 24) {
hours = 0;
}
}
public void setMinutes(int newMinutes) {
minutes = newMinutes;
if (minutes<0 || minutes > 60) {
minutes = 0;
}
}
public void setSeconds(int newSeconds) {
seconds = newSeconds;
if(seconds<0 || seconds > 60) {
seconds = 0;
}
}
/**
* Constructor for objects of class Clock
*/
public Clock(int newHour, int newMinute, int newSecond)
{
if (newHour > -1 || newHour < 24) {
this.hours = newHour;
}
else {
setHours(hours);
}
if (newMinute > -1 || newMinute < 60) {
this.minutes = newMinute;
}
else {
setMinutes(minutes);
}
if (newSecond > -1 || newSecond < 60) {
this.seconds = newSecond;
}
else {
setSeconds(seconds);
}
}
public int getHours() {
return hours;
}
public int getMinutes() {
return minutes;
}
public int getSeconds() {
return seconds;
}
public String toString() {
return hours + ":"+minutes+":"+seconds;
}
public void tick() {
seconds = seconds +1;
if(seconds >= 60)
{
minutes ++;
seconds = 0;
}
if(minutes >= 60)
{
hours++;
minutes = 0;
}
if(hours >=24)
{
hours = 0;
}
}
}
The next piece is the tester code.
public class ClockTest {
public static void main(String [] args){
//Create some clocks and print their times
Clock c1 = new Clock(-3,-21,-30);
System.out.println("T1: "+ c1);
c1 = new Clock(24,60,60);
System.out.println("T2: "+ c1);
c1 = new Clock(3,21,30);
System.out.println("T3: "+ c1);
//Tick the clock twice and print its time
c1.tick();
c1.tick();
System.out.println("T4: "+ c1);
c1 = new Clock(3,30,59);
c1.tick();
System.out.println("T5: "+ c1);
c1 = new Clock(3,59,59);
c1.tick();
System.out.println("T6: "+ c1);
c1 = new Clock(23,59,59);
c1.tick();
System.out.println("T7: "+ c1);
c1 = new Clock(0,0,1);
c1.tick();
System.out.println("T8: "+ c1);
c1 = new Clock(1,1,1);
c1.setHours(22);
c1.setMinutes(30);
c1.setSeconds(35);
System.out.println("T9: "+ c1);
System.out.println("T10: " + c1.getHours() + ":"
+c1.getMinutes() + ":" + c1.getSeconds());
}
}
Your condition is wrong.
When you write this:
if (newHour > -1 || newHour < 24) {
You really mean this:
if (newHour > -1 && newHour < 24) {
#nicomp is correct and you should also be using >= 24 and 60 instead of >. You might consider changing the constructor for Clock to
public Clock(int newHour, int newMinute, int newSecond) {
setHours(newHour);
setMinutes(newMinute);
setSeconds(newSecond);
}
and then do all of your validation in the set methods, instead of having some validation in the set methods and some in the constructor.

Attempting to add an increment method to a time class

I am attempting to add an increment method for a time class I have. I have modified the original code to only have one private integer "totalseconds" that reads the amount of seconds since midnight. That part of the code works fine but now I am trying to create a method that increments the setSecond, setMinute, and setHour. The problem (I believe) I am having is that these set methods all receive their values from totalseconds not int hour, int minute, int second as before. When I run the test for it the way I have it now I get errors at lines 36, 75 (when attempted to increment seconds via Tick method) and 101 (again only when incrementing seconds via Tick method). I have attached both the Time2 class and Time2Test app for reference.
public class Time2 {
private int totalseconds;
//no argument constructor
public Time2()
{
this(0,0,0); //invoke constructor with three arguments default to 0
}
//constructor with hour supplied minute and second default to 0
public Time2(int hour)
{
this(hour, 0, 0); //invoke constructor with 3 args
}
//constructor with hour and minute supplied seconds default to 0
public Time2(int hour, int minute)
{
this(hour, minute, 0); //invoke constructor with 3 args
}
//Time2 constructor with hour minute and second supplied also tests
public Time2(int hour, int minute, int second)
{
this.totalseconds = (hour * 3600);
this.totalseconds += (minute * 60);
this.totalseconds += (second);
}
public Time2(Time2 time)
{
//invoke constructor with 2 args
this(time.getHour(), time.getMinute(), time.getSecond());
}
// SET and GET methods start here, also Universal time conversion and check
public void setTime(int hour, int minute, int second)
{
if (hour < 0 || hour >= 24)
throw new IllegalArgumentException("Hour must be 0-23");
if (minute < 0 || minute >= 59)
throw new IllegalArgumentException("Minute must be 0-59");
if (second < 0 || second >= 59)
throw new IllegalArgumentException("Hour must be 0-59");
this.totalseconds = (hour * 3600);
this.totalseconds += (minute * 60);
this.totalseconds += second;
}
//validate and set hour
public void setHour(int hour)
{
if (hour < 0 || hour >= 23)
throw new IllegalArgumentException("Hour must be 0-23");
this.totalseconds = (hour * 3600);
}
//validate and set minute
public void setMinute(int minute)
{
if (minute < 0 || minute >= 59)
throw new IllegalArgumentException("Minute must be 0-59");
this.totalseconds += (minute * 60);
}
//validate and set second
public void setSecond(int second)
{
if (second < 0 || second >= 59)
throw new IllegalArgumentException("Second must be 0-59");
this.totalseconds += second;
}
//Get Methods start here
//Get hour
public int getHour()
{
return totalseconds / 3600;
}
//get minute
public int getMinute()
{
return (totalseconds - (3600 * getHour())) / 60;
}
//get second
public int getSecond()
{
return totalseconds - (3600 * getHour())- (60 * getMinute());
}
//Assignment 1-2 tick methods start here.
public void Tick()
{
setSecond(totalseconds ++);
if (totalseconds >= 59) incrementMinute();
}
public void incrementMinute()
{
setMinute( totalseconds ++);
if ( totalseconds >= 59) incrementHour();
}
public void incrementHour()
{
setHour ( this.totalseconds ++);
}
//convert our string to universal format (HH:MM:SS)
public String ToUniversalString()
{
return String.format(
"%02d:%02d:%02d", getHour(), getMinute(), getSecond());
}
//conver to standard format (H:MM:SS AM or PM)
public String toString()
{
return String.format("%d:%02d:%02d %s",((getHour() == 0 || getHour() ==
12) ? 12 : getHour() % 12), getMinute(), getSecond(), (getHour()
< 12 ? "AM" : "PM"));
}
}//end class Time2
public class Time2Test
{
public static void main(String[] args)
{
Time2 t1 = new Time2(); //00:00:00
Time2 t2 = new Time2(2); //02:00:00
Time2 t3 = new Time2(21, 34); //21:34:00
Time2 t4 = new Time2(12, 25, 42); //12:25:42
Time2 t5 = new Time2(t4); //12:25:42
System.out.println("Constructed with:");
displayTime("t1: all default arguments", t1);
displayTime("t2: hour specified; defaults for minute and second", t2);
displayTime("t3: hour and minute supplied second defaulted", t3);
displayTime("t4: hour minute and second supplied", t4);
displayTime("t5: Time2 object t4 specified", t5);
//attempt to initialize t6 with invalid args
try
{
Time2 t6 = new Time2(27,74,99); //all invalid values
}
catch (IllegalArgumentException e)
{
System.out.printf("%nException while initializing t6: %s%n",
e.getMessage());
}
System.out.println("Time before increment minute method");
System.out.printf("%s\n", t4.toString());
t4.Tick();
t4.incrementMinute();
t4.incrementHour();
System.out.println("Time after increment minute method");
System.out.printf("%s\n", t4.toString());
}
//display Time2 object in 24 hour and 12 hour formats
private static void displayTime(String header, Time2 t)
{
System.out.printf("%s%n %s%n %s%n", header, t.ToUniversalString(),
t.toString());
}
}

Result does not show, date validation

Any idea why my code won't show the result? Maybe I messed up something, just new to programming by the way.
The goal of the program is to see if the date given by the main class is valid or not, it's not that specific on details such as the month of February and leap years so its pretty simple.
This is my DataRec.java :
public class DateRec {
int month, day, year;
boolean good;
public DateRec (){
month = 1;
day = 1;
year = 2008;
good = true;
}
public DateRec (int setMonth, int setDay, int setYear){
month = setMonth;
day = setDay;
year = setYear;
}
public void validate (){
if ((month < 0) || (month > 12)){
good = false;
if (year == 0)
good = false;
if ((day < 0) || (day > 31))
good = false;
}
}
#Override
public String toString() {
if (good = true) {
return String.format("%dd/%dd/%dddd", month, day, year);
} else {
return String.format("%dd/%dd/%dddd", month, day, year);
}
}
}
This is my main class DataRecTest.java:
public class DateRecTest {
public static void main (String[] args){
DateRec today = new DateRec(1,2,2014);
DateRec anyDay = new DateRec();
DateRec noDay = new DateRec(13,31,2014);
anyDay.validate();
today.validate();
noDay.validate();
today.toString();
anyDay.toString();
noDay.toString();
}
}
Default value of boolean (good) is false so you need to initialized good in constructor or validate() function i.e
good = true; // in constructor or validate function
To see the results you need to print them.
//To print in java use System.out.print() or println();
System.out.println(today.toString());
//or simply
System.out.println(today); // println will call today.toString() internally
[EDIT]
Since you are storing result in good I recommend the following:
public DateRec (int setMonth, int setDay, int setYear){
month = setMonth;
day = setDay;
year = setYear;
good = true;
validate();
}
Now you don't need to call validate() every-time; just check the value of good
your validate() is wrong.... It will always be set t false (default value) in whenever you use the 3- argument constructor. You are not setting it to true when date is correct.
change it to,
public void validate (){
if ((month <= 0) || (month > 12) || (year==0) || (day<=0) || (day>31)){
good = false;
}
else
{
good=true;
}

Categories

Resources