Goal: The goal of this assignment is to help students understand the use of JUnit to test Java
code.
Description: In this assignment you will create a set of unit tests, to test the behavior of the code
written for Assignment 1. To keep things consistent, please use the solution to assignment 1
provided by the instructor. You can find the solution on TRACS, under Resources >
Assignment-related material > Assignment
Solution
s.
A unit test is an automated piece of code that invokes a unit of work in the system and then
checks a single assumption about the behavior of that unit of work. A unit of work is a single
logical functional use case in the system that can be invoked by some public interface (in most
cases). A unit of work can span a single method, a whole class or multiple classes working
together to achieve one single logical purpose that can be verified.
Think of unit testing as a way to test the behavior of the code (or parts of the code) written,
without actually having to run the program. For example, in the case of assignments 1, assume
that the front-end (console user interface) part of the program and the back-end part of the
program (dealership database management) are written by two different developers. How would
the developer of the back-end be able to ensure that the code he/she has written does what it is
supposed to do without having access to the front-end?
A good unit test is:
• Able to be fully automated
• Has full control over all the pieces running.
• Can be run in any order, if part of many other tests
• Runs in memory (no DB or File access, for example)
• Consistently returns the same result (You always run the same test, so no random numbers, for
example.)
• Runs fast
• Tests a single logical concept in the system
• Readable
• Maintainable
• Trustworthy (when you see its result, you don’t need to debug the code just to be sure)
In this assignment, you are asked to create JUnit tests to test the classes and methods written for
assignment 1. First you should consider testing the behavior of theses classes/methods under
normal operation scenarios. For example, to test the method findCar(String vin) of the class
Dealership, you may need to create a test method, which creates a mock Car object and adds it to
the carList before the method findCar can be called to search for it. To ensure that everything
worked as planned, you can then search for the car using its VIN and see if the correct car is
found. Mock objects can be created either in the same test method or before any test methods are
run, using the @BeforeClass annotation.
Subsequently, you can consider creating test cases for unusual scenarios, e.g. when a certain
input or behavior is expected to cause an exception to be thrown, or when a user input is not as
expected.
At the end create a TestRunner class, which has a main method that runs the unit tests that you
have created, and prints out the test results.
Tasks:
1. Implement the JUnit tests to test only the.
Goal The goal of this assignment is to help students understand the.pdf
1. Goal: The goal of this assignment is to help students understand the use of JUnit to test Java
code.
Description: In this assignment you will create a set of unit tests, to test the behavior of the code
written for Assignment 1. To keep things consistent, please use the solution to assignment 1
provided by the instructor. You can find the solution on TRACS, under Resources >
Assignment-related material > Assignment
Solution
s.
A unit test is an automated piece of code that invokes a unit of work in the system and then
checks a single assumption about the behavior of that unit of work. A unit of work is a single
logical functional use case in the system that can be invoked by some public interface (in most
cases). A unit of work can span a single method, a whole class or multiple classes working
together to achieve one single logical purpose that can be verified.
Think of unit testing as a way to test the behavior of the code (or parts of the code) written,
without actually having to run the program. For example, in the case of assignments 1, assume
that the front-end (console user interface) part of the program and the back-end part of the
program (dealership database management) are written by two different developers. How would
the developer of the back-end be able to ensure that the code he/she has written does what it is
supposed to do without having access to the front-end?
A good unit test is:
• Able to be fully automated
• Has full control over all the pieces running.
• Can be run in any order, if part of many other tests
• Runs in memory (no DB or File access, for example)
• Consistently returns the same result (You always run the same test, so no random numbers, for
example.)
• Runs fast
• Tests a single logical concept in the system
• Readable
• Maintainable
• Trustworthy (when you see its result, you don’t need to debug the code just to be sure)
In this assignment, you are asked to create JUnit tests to test the classes and methods written for
assignment 1. First you should consider testing the behavior of theses classes/methods under
normal operation scenarios. For example, to test the method findCar(String vin) of the class
Dealership, you may need to create a test method, which creates a mock Car object and adds it to
2. the carList before the method findCar can be called to search for it. To ensure that everything
worked as planned, you can then search for the car using its VIN and see if the correct car is
found. Mock objects can be created either in the same test method or before any test methods are
run, using the @BeforeClass annotation.
Subsequently, you can consider creating test cases for unusual scenarios, e.g. when a certain
input or behavior is expected to cause an exception to be thrown, or when a user input is not as
expected.
At the end create a TestRunner class, which has a main method that runs the unit tests that you
have created, and prints out the test results.
Tasks:
1. Implement the JUnit tests to test only the class Dealership.java, including all its methods. Try
to be creative by coming up with test cases that can test as many different situations as possible.
You don’t need to test the classes Car.java and MainClass.java.
2. Use a standard Java coding style to improve your program’s visual appearance and make it
more readable. I suggest the BlueJ coding style: http://www.bluej.org/objects-
first/styleguide.html
3. Use Javadoc to document your code.
Dealership Program
import java.io.IOException;
import java.io.FileReader;
import java.io.PrintWriter;
import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;
/**
* This class is used to represent a database interface for a list of
* Car's. It using a plain-text file "cars.txt" to store and write
* car objects in readable text form. It contains an ArrayList
* called carList to store the database in a runtime friendly data
* structure. The carList is written to "cars.txt" at the end of
* the Dealership object's life by calling flush().
* This class also provides methods for adding, remove, and searching for cars
* from the list.
*
* @author Vangelis Metsis
*/
3. public class Dealership {
private ArrayList carList;
/**
* This constructor is hard-coded to open "cars.txt" and
* initialize the carList with its contents. If no such file
* exists, then one is created. The contents of the file are "loaded" into
* the carList ArrayList in no particular order. The file is then closed
* during the duration of the program until flush() is called.
* @throws IOException
*/
public Dealership() throws IOException {
carList = new ArrayList<>();
Scanner carDatabase;
File dataFile = new File("cars.txt");
// If data file does not exist, create it.
if (!dataFile.exists()) {
System.err.println("Cars.txt does not exist, creating one now . . .");
//if the file doesn't exists, create it
PrintWriter pw = new PrintWriter("cars.txt");
//close newly created file so we can reopen it
pw.close();
}
carDatabase = new Scanner(new FileReader(dataFile));
//Initialize the Array List with cars from cars.txt
while (carDatabase.hasNextLine()) {
// split values using the space character as separator
String[] temp = carDatabase.nextLine().split(" ");
carList.add(new Car(temp[0], temp[1], temp[2], Integer.parseInt(temp[3]),
Integer.parseInt(temp[4]), Float.parseFloat(temp[5])));
}
//Cars list is now in the Array List Completely so we can close the file
carDatabase.close();
}
/**
* Method showCars displays the current list of cars in the Arraylist in no
* particular order.
4. *
*/
public void showCars() {
showCars(carList);
}
/**
* Private method used as an auxiliary method to display a given ArrayList
* of cars in a formatted manner.
*
* @param cars the car list to be displayed.
*/
private void showCars(ArrayList cars) {
System.out.println("
_____________________________________________________________________________
_____");
System.out.println("| Entry | VIN | Make | Model | Year | Mileage | Price |");
System.out.println("|----------------------------------------------------------------------------------|");
for (int i = 0; i < cars.size(); i++) {
System.out.println(String.format("| %-6s| %-7s| %-15s| %-15s| %-5s| %-8s| $%-12s|",
Integer.toString(i + 1), cars.get(i).getVin(), cars.get(i).getMake(), cars.get(i).getModel(),
Integer.toString(cars.get(i).getYear()), Integer.toString(cars.get(i).getMileage()),
String.format("%.2f", cars.get(i).getPrice())));
}
System.out.println("|____________________________________________________________
______________________| ");
}
/**
* This method displays cars that have a price within the range of
* low to high.
*
* @param low a float that is the lower bound price.
* @param high a float that is the upper bound price.
*/
public void showCarsRange(float low, float high) {
ArrayList cars = new ArrayList<>();
for (Car car : carList) {
5. if ((low <= car.getPrice()) && (car.getPrice() <= high)) {
cars.add(car);
}
}
showCars(cars);
}
/**
* This method can be used to search for a car in the Arraylist of cars.
*
* @param vin a String that represents the vehicle
* identification number of the car that to be searched for
* @return the int index of the car in the Arraylist of cars,
* or -1 if the search failed.
*/
public int findCar(String vin) {
int index = -1;
for (int i = 0; i < carList.size(); i++) {
String temp = carList.get(i).getVin();
if (vin.equalsIgnoreCase(temp)) {
index = i;
break;
}
}
return index;
}
/**
* This method is used to add a car to the carList ArrayList. In order for a
* car to be added to the ArrayList it must comply with the following:
*
* 1. The car is not already in the ArrayList according to the VIN
* as the unique key.
*
* 2. The VIN string matches the following regular expression:
* "[A-Za-z0-9]{5}" or in other words: it
6. * is 5 avinhanumeric characters.
*
* 3. The make of the car is only alphanumeric characters.
*
* 4. The model of the car is only alphanumeric or contains a dash "-".
*
* 5. The year model must be exactly four digits.
*
* 6. The price must be non-negative.
*
* @param toAdd the Car object to add to the
* carList
*/
public void addCar(String vin, String make, String model, String year, String mileage, String
price) {
if (this.findCar(vin) != -1) {
System.err.println("Car already exists in database. ");
return;
}
if (!vin.matches("[A-Za-z0-9]{5}")) {
System.err.println("Invalid VIN: not proper format."
+ "VIN must be at least 5 alphanumeric characters.");
return;
}
if (!make.matches("[A-Za-z0-9]+")) {
System.err.println("Invalid make type: "
+ "The car's make must be an alphanumeric string.");
return;
}
7. if (!model.matches("[A-Z0-9a-z-]+")) {
System.err.println("Invalid model type: "
+ "The car's model must be a non-numeric alphabet string.");
return;
}
if (!year.matches("[0-9]{4}") ) {
System.err.println("Invalid year: "
+ "The car's year of manufacture must be a 4 digit number. ");
return;
}
if (!mileage.matches("[0-9]{1,6}")) {
System.err.println("Invalid milage: "
+ "The car's mileage has to be an integer number between 0 and 999999. ");
return;
}
if (Float.parseFloat(price) < 0) {
System.err.println("The entered price cannot be negative.");
return;
}
//If passed all the checks, add the car to the list
carList.add(new Car(vin, make, model, Integer.parseInt(year),
Integer.parseInt(mileage), Float.parseFloat(price)));
System.out.println("Car has been added. ");
}
/**
* This method will remove a car from the carList ArrayList. It
* will remove the first instance of a car that matches the car that was
* passed to this method in the carList using the
* equals() override in the class Car. If no such
* car exists, it will produce an error message.
*
8. * @param toDelete the car object to be removed.
*/
public void removeCar(Car toDelete) {
if (carList.remove(toDelete)) {
System.out.println("Car was removed. ");
} else {
System.err.println("Car does not exist in database.");
}
}
/**
* This method is used to retrieve the Car object from the
* carList at a given index.
*
* @param i the index of the desired car object.
* @return the car object at the index or null if the index is
* invalid.
*/
public Car getCar(int i) {
if (i < carList.size() && i >= 0) {
return carList.get(i);
} else {
System.err.println("Invalid Index. Please enter another command or 'h' to list the
commands.");
return null;
}
}
/**
* This should be the last method to be called from this class. It opens
* "cars.txt" and overwrites it with a text representation of
* all the cars in the carList.
* @throws IOException
*/
public void flush() throws IOException {
PrintWriter pw = new PrintWriter("cars.txt");
for (Car c : carList) {
pw.print(c.toString());