This is a small Java application that is designed to calculate a departments total monthly expenses by adding the amounts paid to all the employees in that department. The departments employees are arranged in a hierarchy, which this app seeks to take into account with how it arranges objects.
I'm new to JUnit and unit testing. I'm attempting to run a test comparing my actual total to an expected total. However, I'm getting a number of error(detailed in the source code below).
Note I'm using: Windows 8.1, Java SE 8, eclipse Luna, JUnit 4.
I have 1 main question, & 1 side questions:
Could you help me to understand what is causing these errors and what I can do to correct them?
I'm trying to improve my documentation style by moving from 'comments' to something a little more professional. Could this documentation be improved?
Thanks for taking a look.
Unit Test
package test;
import static org.junit.Assert.*;
import org.junit.Test;
import expenseApp.Developer; // The import expenseApp cannot be resolved
import expenseApp.Manager; // The import expenseApp cannot be resolved
import expenseApp.QATester; // The import expenseApp cannot be resolved
/**
* TestClass evaluates a departments actual total expenses,
* by comparing them to a projected total.
* #author Reed
*/
public class TestClass {
/**
* testOne() compares a departments actual total expenses with a projected total of $2100.00.
* This departments employees create the following hierarchy:
* managerA <-- managerB <-- tester1 & dev1.
*/
#Test
public void testOne()
{
QATester tester1 = new QATester(); // Multiple markers at this line - QATester cannot be resolved to a type x2
Developer dev1 = new Developer(); // Multiple markers at this line - Developer cannot be resolved to a type x2
Manager managerB = new Manager(); // Multiple markers at this line - Manager cannot be resolved to a type x2
managerB.add(tester1);
managerB.add(dev1);
Manager managerA = new Manager(); // Multiple markers at this line - Manager cannot be resolved to a type x2
managerA.add(managerB);
assertEquals(managerA.getTotalExpenses(), 2100.00, 0.00);
fail("Not yet implemented"); // automatically generated, should I use this?
}
}
App
//Employee
package expenseApp;
/**
* Employee is the abstract superclass of Manager, QATester, and Developer.
* Employee declares public abstract double getExpenses().
* #author Reed
*/
public abstract class Employee
{
/**
* getExpenses() returns the monthly allocation amount of a Manager, Developer, or QATester object.
* #return a double values representing what the specified Employee is paid each month.
*/
public abstract double getExpenses();
}
// QATester
package expenseApp;
/**
* QA Testers warrant a monthly allocation of $500.00, per QA Tester.
* QATester extends Employee.
* #author Reed
*/
public class QATester extends Employee
{
/**
* getExpenses() returns a QA Testers monthly allocation amount.
* #return a double value of 500.00.
*/
#Override
public double getExpenses()
{
return 500.00;
}
}
// Developer
package expenseApp;
/**
* Developers warrant a monthly allocation of $1000.00, per Developer.
* Developer extends Employee.
* #author Reed
*/
public class Developer extends Employee
{
/**
* getExpenses() returns a Developers monthly allocation amount.
* #return a double value of 1000.00.
*/
#Override
public double getExpenses()
{
return 1000.00;
}
}
// Manager
package expenseApp;
import java.util.ArrayList;
/**
* Managers warrant a monthly allocation of $300.00, per Manager.
*
* A manager is at the top of a hierarchical relationship,
* in which one manager oversees employees such as developers,
* QA testers, & other managers. An employee's title is associated with
* an amount that type of employee is paid monthly.
* A compete hierarchy constitutes all the employees of a department.
* A departments expenses can be determined by adding the amounts
* paid to the employees in a hierarchy.
*
* Manager extends Employee.
*
* #author Reed
*/
public class Manager extends Employee
{
private ArrayList<Manager> managerList = new ArrayList<>();
private ArrayList<Employee> employeeList = new ArrayList<>();
/**
* Add() adds employees to a list.
* If the employee is a manager, managerList.
* Else, the employee is a developer or QA tester, employeeList.
* #param employee
*/
public void add(Employee employee)
{
if(employee instanceof Manager)
{
managerList.add((Manager) employee);
}
else
{
employeeList.add(employee);
}
}
/**
* getExpenses() returns a Mangers monthly allocation amount.
* #return a double value of 300.00.
*/
#Override
public double getExpenses()
{
return 300.00;
}
/**
* getTotalExpenses() adds the values in managerList and employeeList,
* calculating a departments total monthly expenses.
* #return the value of totalExpenses.
*/
public double getTotalExpenses()
{
double totalExpenses = 0.00;
for(Manager manager : managerList)
{
totalExpenses += manager.getTotalExpenses();
}
for(Employee employee : employeeList)
{
totalExpenses += employee.getExpenses();
}
return totalExpenses;
}
}
import expenseApp.Developer; // The import expenseApp cannot be resolved
This error means that Eclipse can't find the code for the class Developer. This problem is not related to JUnit or unit tests.
Make sure your build path contains the necessary JARs and projects.
Also, remove the fail() at the end of the test since you have now implemented the test.
documentation
A better way to document is to use variables:
double expected = 2100.0;
double maxDelta = 1e-6;
assertEquals(expected, managerA.getTotalExpenses(), maxDelta);
The variables explain what a value means. "2100" means nothing. "expected" communicates: That's the expected result.
You could use expectedDollars to say "this value is in dollars".
If you have only short pieces of code, don't document them. People can read the code to understand what is going on. But you can help them by adding methods with useful names:
Manager managerB = managerWithADevAndTester();
Manager managerA = createManagerFor( managerB );
or, if you prefer simple DSLs:
Manager managerB = createManagerFor(
new QATester(),
new Developer()
);
Manager managerA = createManagerFor( managerB );
Based on our comment discussion, it seems you wrote your unit tests in another Eclipse project. Typically tests are located within the same project, thus they benefit from having all the project classes on the classpath.
If you'd like to use a separate project, you'll need to edit the test project properties to tell Eclipse that you have a dependency on your main project.
The fail call at the end of the test case should be removed, that will always fail the test regardless of the assertion result on the line above.
Related
So I have been looking around and reading up a lot of forums and the java documentation but I can't seem to get a solid solution for what I am trying to do.
Essentially I have a Module class as shown below:
/**
* MODULE CLASS
* This class will be the base for every Module inputed into the system
* #author George
*/
public class Module {
// -=VARIABLE DECLARATIONS=-
private String moduleName; /* String variable to store the name of the module */
private String moduleLeader; /* String variable to store the name of the module leader */
// -=GETTERS=-
public String getModuleName() {return this.moduleName;} /* Will return the name of the module */
public String getModuleLeader() {return this.moduleLeader;} /* Will return the name of the module leader */
// -=SETTERS=-
public void setModuleLeader(String l) {this.moduleLeader = l;} /* Sets the name of the module leader to the inputed name */
public void setModuleName(String n) {this.moduleName = n;} //THIS NEEDS TO BE ADDED TO DESIGN DIAGRAMS
// -=CONSTRUCTOR=-
/**
* Constructor to make a new object for the module
* #param n (NAME) - String input to set the name of the module
* #param l (LEADER) - String input to set the name of the module leader
*/
public Module(String n, String l) {
this.moduleName = n;
this.moduleLeader = l;
}
}
On my GUI, each module is represented as its own button which upon clicking will take you to the module's page using CardLayout. I also have a button where the user can add a module, this is where my issue comes into place. Obviously a Module object would be defined as:
Module newModule = new Module("name", "leader");
But how would this allow more than one object to be created. The name of the module would come from user input so there is no way I can put the name of the object in the source code and from what I have read you cannot set the object name using a variable.
Lets say for example, during runtime, the user would want to create two modules. One with the name of "Java" and one with the name of "Python". How would I go about doing this? Obviously the first object would be created just fine using the initialization above, but the name of the object would be stuck as newModule. But then it would not be able to create the second object as it cannot have two objects with the same name. I have spent some time trying to understand HashMaps to see if that could be of any use to me but quite frankly I find it quite confusing and again, I can't tell if that is the correct solution.
I hope I have worded this correctly and you can understand my problem. Any help with this would be greatly appreciated.
Thanks in advance.
I'm trying to figure out how to get the relativeAtomicMass from one class named ChemicalElement onto another called MolarMass in which I try to figure out the atomicmass of an element given it's symbol then find out a compound mass. I'm not sure how to return a double, I tried using a toString to do it since that's what a tutor taught me to do but I'm not sure if it's the correct way that my teacher wants me to do it. I know I need to get the relativeAtomicMass onto MolarMass to finish the assignment but i'm stuck at the moment. Heres the code for my assignment:
package chemical;
public class ChemicalElement {
// Properties (fields/variables): This time we leave give them default visibility, which gives
// other classes in the same package (i.e. the same directory) full access to them, for brevity.
/** The number of protons */
int atomicNumber;
/** 1-3 letter IUPAC symbol */
String symbol;
/** Full name */
String name;
/** Relative atomic mass () */
double relativeAtomicMass;
/** Row in the periodic table */
int period;
/** Column in the periodic table */
int group;
// Actions (methods): For now we provide a constructor to initialize all fields.
/**
* Constructs a new ChemicalElement object with the given properties.
*
* #param atomicNumber the number of protons
* #param symbol the IUPAC symbol
* #param name the full name
* #param relativeAtomicMass the average atomic mass relative to carbon-12
* #param period the row in the periodic table
* #param group the column in the periodic table
*/
public ChemicalElement(int atomicNumber, String symbol, String name, double relativeAtomicMass,
int period, int group) {
this.atomicNumber = atomicNumber;
this.symbol = symbol;
this.name = name;
this.relativeAtomicMass = relativeAtomicMass;
this.period = period;
this.group = group;
}
public String toString()
{
return name;
}
}
package chemical;
import java.net.URL;
import java.util.Scanner;
import java.util.Arrays;
public class MolarMass {
public static void main(String[] compoundTokens) throws Exception {
ChemicalElement[] elements = readElementData();
//System.out.printf("%.6f%n", compoundmass(elements, compoundTokens));
System.out.println(Arrays.toString(elements));
}
/**
* Loads data about all chemical elements into an array.
*
* #return an array containing references to objects describing all 118 chemical elements
* #throws Exception if anything goes awry (we only know how to pass the buck)
*/
private static ChemicalElement[] readElementData() throws Exception {
ChemicalElement[] elements = new ChemicalElement[119];
Scanner dataFile =
new Scanner(new URL("http://jeff.cis.cabrillo.edu/datasets/elements").openStream());
while (dataFile.hasNext()) {
// Example line: 1 H Hydrogen 1.008 1 1
int atomicNumber = dataFile.nextInt();
elements[atomicNumber] = new ChemicalElement(atomicNumber, dataFile.next(), dataFile.next(),
dataFile.nextDouble(), dataFile.nextInt(), dataFile.nextInt());
}
return elements;
}
/**
* Determines the molar mass of a compound.
*
* #param elements an array containing references to objects describing all 118 chemical elements
* #param tokens a compound formula
* #return the molar mass of the given compound
*/
// private static double compoundMass(ChemicalElement[] elements, String[] tokens) {
// TODO
/**
* Determines the relative atomic mass of an element, given its symbol.
*
* #param elements an array containing references to objects describing all 118 chemical elements
* #param symbol the symbol of the element in question
* #return the relative atomic mass of the given element
*/
// private static double relativeAtomicMass(ChemicalElement[] elements, String symbol) {
// TODO
}
Also i'd imagine that once I get the relative atomic mass onto molarmass it would be easy to fill out the code for relativeatomicmass but how would I use that to create compounds?
Thanks any help would be appreciated.
So for my programming class, we are supposed to make a Junit test for one of our classes that inherits from an abstract class. I've just been really confused on writing Junit tests since I don't feel like there's enough examples online. My first question is, do we test getters and setters? My professor instructed us to "select all" the methods when setting up our test, but on a website she asked us to read, they advised not to test getters and setters because JVM already has testers for them. My second and most important question is can you test an entire constructor? My code below basically has an undergrad student inheriting from an abstract student class. I'm assuming I should test to make sure that the undergrad student is in fact an undergrad student and not a master student, but I don't know how to exactly test an entire constructor. Any tips would be greatly appreciated!!
public abstract class AbstractStudent {
/**
* First name of a student.
*/
private String myFirstName;
/**
* Last name of a student.
*/
private String myLastName;
/**
* Student 9-digit ID.
*/
private String myID;
/**
* Number of credit hours completed by a student.
*/
private int myCreditHours;
/**
* Current student GPA.
*/
private double myGPA;
/**
* Student gender.
*/
private Gender myGender;
/** Student date of birth.
*
*/
private Date myBirth;
/**
* Private constructor to prohibit default instantiation.
*/
/**
* #param theFirstName Adds the first name into the constructor
* #param theLastName Adds the last name into the constructor
* #param theID Adds the ID into the constructor
* #param theCreditHours Adds the credit hours into the constructor
* #param theGPA Adds the GPA into the constructor
* #param theGender Adds the gender into the constructor
* #param theBirth Adds the birth into the constructor
*/
public AbstractStudent(final String theFirstName, final String theLastName,
final String theID, final int theCreditHours, final double theGPA,
final Gender theGender, final Date theBirth) {
myFirstName = theFirstName;
myLastName = theLastName;
myID = theID;
myCreditHours = theCreditHours;
myGPA = theGPA;
myGender = theGender;
myBirth = new Date(theBirth.getTime());
}
And the UndergradStudent class:
public class UndergradStudent extends AbstractStudent {
/**
* Student status.
*/
private StudentStatus myStatus;
/**
* Parameterized constructor - constructors a Student object.
* #param theFirstName is a string representing the first name of a student, != null
* #param theLastName is a string representing the last name of a student, != null
* #param theID is a string of 9 characters representing student ID
* #param theCreditHours is an integer number >=0 representing number of credit hours
* taken by a student
* #param theGPA is a double number representing GPA, a GPA must be >= 0 and <= 4.0
* #param theStatus is a string representing student status, != null
* #param theGender is a character representing student gender, != null
* #param theBirth is a date representing student birth date; a student cannot be younger
* than 10 years old
* #custom.post Student object constructed; if invalid parameters passed,
* student is in an invalid state.
*/
public UndergradStudent(final String theFirstName, final String theLastName,
final String theID, final int theCreditHours, final double theGPA,
final StudentStatus theStatus, final Gender theGender,
final Date theBirth) {
super(theFirstName, theLastName, theID, theCreditHours, theGPA, theGender, theBirth);
myStatus = theStatus;
}
I can't really comment on the intention of your professor but when writing unit tests you are aiming to test single units of functionality. Most developers consider testing basic POJO behaviour where a get method returns a constructor property as redundant, however if you are writing getter/setter methods which are stateful they are worth testing.
One way you could test the whole constructor of UndergradStudent is to construct an instance either as a private final variable or using JUnit's #BeforeClass annotation and writing a separate #Test for each property getter.
There is a class named "Bill".
Bill can be either "Electricity" , "Food" or "Customer" which are all POJO.
So it contains three objects:
public class Bill{
private Electricity el1;
private Food el2;
private Customer el3;
//setters and getters
public setElectricity(...)
...
}
List of Bills are populated using some DTOs.
And each time, I need to check all elements to be sure what type of bill am I having.
My goal is to refactor this design.
I could also have one object and set the content regarding to the type, but is it having any standard pattern?
Is there any pattern for classes who can be a class based on the type that is requested?
I mean Bill will be either electricity, food or customer regarding to the populating time.
Note: My application favored composition over inheritance
It is also a “design by contract” based application.
Edit:
Bill is not an abstract of it's objects.
Lets assume, food is just specification of food like color and receipt!
A bill can be one and only one of the object at a point of time.
Bill is an abstract entity hence it should be an abstract class. All other type of bills should extend from it such as : ElectricityBill, FoodBill, GasBill etc
If ElectricityBill, FoodBill, GasBill has some common functionality, then create Bill as abstract class and extend other classes from bill.
If they have altogether different behaviour and state (which i doubt)then create Bill as interface and let other concrete class implement them.
i usually call it simple factory pattern(dont confuse it with factory method/abstract factory pattern)
public class BillFactory
{
Bill createBill(String type)
{
if(type.equals("Electricity"))
{
bill=new ElectricityBill();
}
........
}
}
As you have a big object with many parameters out of which some can be optional.
You can use Builder Pattern for creating the instance of your Bill class.
Unlike the abstract factory pattern and the factory method pattern
whose intention is to enable polymorphism, the intention of the
builder pattern is to find a solution to the telescoping constructor
anti-pattern. The telescoping constructor anti-pattern occurs when the
increase of object constructor parameter combination leads to an
exponential list of constructors. Instead of using numerous
constructors, the builder pattern uses another object, a builder, that
receives each initialization parameter step by step and then returns
the resulting constructed object at once.
Suppose you are building a house:
public House getHouse() {
return this.houseBuilder.getHouse();
}
public void constructHouse() {
this.houseBuilder.buildBasement();
this.houseBuilder.buildStructure();
this.houseBuilder.bulidRoof();
this.houseBuilder.buildInterior();
}
Example from Java Papers
If Bill only can contain one instace, why dont u use a interface?
public interface Billable {
double getPrize();
}
public class Electricity implements Billable {
#Override
public double getPrize() {
return 20.0;
}
}
public class Bill {
/**
* Billable to bill.
*/
Billable billable;
/*
* Discount percent applied to bill.
*/
#Min(0)
#Max(100)
double discount;
/**
* VAT percent applied to bill.
*/
#Min(0)
#Max(100)
double vat;
public Bill(#NotNull Billable billable) {
this.billable = billable;
discount = 10.0;
vat = 21.0;
}
public double getFinalPrize() {
double discountFactor = 1 - discount / 100;
double vatFactor = 1 + vat / 100;
return billable.getPrize() * discountFactor * vatFactor;
}
public static void main(String[] args) {
Electricity electricity = new Electricity();
Bill electricityBill = new Bill(electricity);
System.out.println(electricityBill.getFinalPrize());
}
}
I have build an application for dynamic compile java source code and fetch the compiled class information and stored to object.
The application required source directory and full qualify class name (ex. MOCG.entity.Person) for adding file to the application.
I use the Janino compiler in this application. I used to implement by javax.tools.ToolProvider compiler but I dont know how to compile multiple file, and it cannot automatically compile related class.
For now my code work just fine but when I try to compile an interface class or abstract class it always return error :
Caused by: org.codehaus.commons.compiler.CompileException: File /Users/chillyprig/IdeaProjects/Mockito/src/lab05/p1/dao/CourseDAO.java, Line 22, Column 9: Identifier expected in member declaration
at org.codehaus.janino.Parser.throwCompileException(Parser.java:2593)
at org.codehaus.janino.Parser.parseInterfaceBody(Parser.java:613)
at org.codehaus.janino.Parser.parseInterfaceDeclarationRest(Parser.java:518)
at org.codehaus.janino.Parser.parsePackageMemberTypeDeclaration(Parser.java:186)
at org.codehaus.janino.Parser.parseCompilationUnit(Parser.java:74)
at org.codehaus.janino.JavaSourceIClassLoader.findIClass(JavaSourceIClassLoader.java:150)
... 46 more
This is an input file :
/**
* Created with IntelliJ IDEA.
* User: Dto
* Date: 12/2/12
* Time: 8:26 AM
* To change this template use File | Settings | File Templates.
*/
package lab05.p1.dao;
import java.util.List;
import java.util.Set;
/**
* This is the example of the DAO interface, you have to implement the implementation class to complete the DAO classes
* #author dto
*/
public interface CourseDAO {
/**
* Get all the courses
* #return all courses stored in the persistence
*/
List<Course> getCourses();
/**
* Get all students which enroll to the courses
* #return all students in the persistence
*/
Set<Student> getStudents();
/**
* Get the course by query the name provided
* #param name the name of the course which the user wants
* #return the course which contains the same name
* null if the course with specific name is not existed
*/
Course getCourseByName(String name);
/**
* Get the Student by id
* #param id the id of the student which we want to find
* #return the student object with the specific id
* The empty student object if the student with the specific id is not exist
*/
Student getStudentById(String id);
}
This is my snipped code for compilation :
private Class compile() throws ClassNotFoundException, SourceDirectoryNotfoundException {
ClassLoader classLoader = null;
try{
classLoader = new JavaSourceClassLoader(
Thread.currentThread().getContextClassLoader(),
new File[] {new File(sourceDir)},
(String) null
);
} catch (NullPointerException e){
throw new SourceDirectoryNotfoundException();
}
Class<?> c = classLoader.loadClass(fullname);
return c;
}
Every suggestion is very appreciate. Any code example would be nice.
Janino is a Java 1.4 compatible compiler -- i.e., it can't handle generics, which were introduced in Java 5. Line 22 is the line that begins List<Course> -- a use of generics, which this compiler can't handle.