diff --git a/README.md b/README.md index e1eb6769..19457301 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,52 @@ ### Part One: The Test Driven Development Cycle (Red, Green, Refactor) -We will follow the best practices of TDD, and we will create our tests first and write production code once we see the test fail. We will create a `Student` and a `StudentTest` class for a grades application, before you start let's analyse the requirements for the `Student` class: +We will follow the best practices of TDD, and we will create our tests first and write production code once we see the test fail. We will create a `students.Student` and a `students.StudentTest` class for a grades application, before you start let's analyse the requirements for the `students.Student` class: - `id` should be a `long` number used to represent a "unique user" in our application. - `name` is a `String` that holds the name of the student. - `grades` is an `ArrayList` that contains a list of `Integer` numbers. 1. Create a new branch called `students-tests` and read carefully the next instructions. + +1. Create a `students.StudentTest.java` class file inside of `src/test/java` (you might have to create these folders yourself) and remember to write the test before the actual production code. We will simulate the `C(reate) R(ead)` from the `CRUD` functionality in our grades application, you should be able to test and create the following requirements: + + - The `students.Student` class should have a constructor that sets both the name and id property, it initializes the grades property as an empty ArrayList. + - The `students.Student` class should have the following methods: + ```java + // returns the student's id + public long getId(); + // returns the student's name + public String getName(); + // adds the given grade to the grades list + public void addGrade(int grade); + // returns the average of the students grades + public double getGradeAverage(); + ``` +1. As always, commit and push all your changes once you're done. +_At the end of the exercise you will end up with a `students.Student.java` and a `students.StudentTest.java` class._ + +#### Bonus + +- Go ahead and try to add the rest of the `CRUD` tests and functionality, write the methods for `updateGrade()` and `deleteGrade()` in the `students.Student` class. + +### Part Two: Testing Legacy Code + +Once you are done with the `students.Student.java` class. + +1. Checkout to the `cohorts-feature` branch, there you will find a `students.Cohort.java` class inside the `src/main/java` folder, this class has already a lot of methods to calculate the cohort average grade and add a student. Let's go ahead and make sure there's sufficient tests for this class to be deployed to production: + +1. Start by creating a new branch called: `cohorts-tests`. +1. Then create a `CohortTest` class and build a test for each of the following requirements: + - A `students.Cohort` instance can add a `students.Student` to the `List` of students. + - A `students.Cohort` instance can get the current `List` of students. + - A `students.Cohort` instance can get the average, and it's being calculated correctly. +1. Go back to the `students.StudentTest` class and refactor the code to avoid any repetition in the test cases, the use of the `@Before` annotation will be useful to achieve this, do the same with this new `CohortTest` class if you find any code repetition as well. + +#### Bonus + +- Follow the TDD cycle and create a new feature to find students by their ID like: `findStudentById(long id)` in the `students.Cohort` class, remember to create the tests first before any production code. + 1. Create a `StudentTest.java` class file inside of `src/test/java` (you might have to create these folders yourself) and remember to write the test before the actual production code. We will simulate the `C(reate) R(ead)` from the `CRUD` functionality in our grades application, you should be able to test and create the following requirements: - The `Student` class should have a constructor that sets both the name and id property, it initializes the grades property as an empty ArrayList. @@ -63,4 +102,4 @@ Once you are done with the `Student.java` class. #### Bonus -- Follow the TDD cycle and create a new feature to find students by their ID like: `findStudentById(long id)` in the `Cohort` class, remember to create the tests first before any production code. \ No newline at end of file +- Follow the TDD cycle and create a new feature to find students by their ID like: `findStudentById(long id)` in the `Cohort` class, remember to create the tests first before any production code. diff --git a/pom.xml b/pom.xml index d9c0c6eb..fb625a46 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ tests 1.0-SNAPSHOT - + 11 11 diff --git a/src/main/java/students/Cohort.java b/src/main/java/students/Cohort.java new file mode 100644 index 00000000..b3403f2b --- /dev/null +++ b/src/main/java/students/Cohort.java @@ -0,0 +1,45 @@ +package students; + +import java.util.ArrayList; +import java.util.List; + +public class Cohort { + + private List students; + + public Cohort() { + this.students = new ArrayList<>(); + } + + public Student getStudentById(long id) { + for(Student student : students) { + if(student.getId() == id) { + return student; + } + } + + // what if we get here? + return null; + } + + public double getCohortAverage() { + // kira says an empty cohort is a failing cohort + if(students.size() == 0) { + return 0; + } + + double avg = 0; + for (Student student: this.getStudents()) { + avg += student.getGradeAverage(); + } + return avg / this.getStudents().size(); + } + + public void addStudent(Student student){ + students.add(student); + } + + public List getStudents() { + return students; + } +} \ No newline at end of file diff --git a/src/main/java/students/Student.java b/src/main/java/students/Student.java new file mode 100644 index 00000000..10947f38 --- /dev/null +++ b/src/main/java/students/Student.java @@ -0,0 +1,40 @@ +package students; + +import java.util.ArrayList; + +public class Student { + + private long id; + private String name; + private ArrayList grades; + + public Student(long id, String name) { + this.id = id; + this.name = name; + this.grades = new ArrayList<>(); + } + + public long getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public ArrayList getGrades() { + return this.grades; + } + + public void addGrade(int grade) { + this.grades.add(grade); + } + + public double getGradeAverage() { + double sum = 0; + for (int grade: this.grades) { + sum += grade; + } + return sum / this.grades.size() ; + } +} diff --git a/src/test/java/students/CohortTest.java b/src/test/java/students/CohortTest.java new file mode 100644 index 00000000..314c86ae --- /dev/null +++ b/src/test/java/students/CohortTest.java @@ -0,0 +1,87 @@ +package students; + +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + +public class CohortTest { + private Cohort emptyCohort, happyCohort; + + private Student s1, s2; + + @Before + public void setup() { + emptyCohort = new Cohort(); + happyCohort = new Cohort(); + + s1 = new Student(1, "S1"); + s1.addGrade(50); + s1.addGrade(55); + s1.addGrade(60); + happyCohort.addStudent(s1); + // s1 average is 55 + + s2 = new Student(2, "S2"); + s2.addGrade(80); + s2.addGrade(87); + s2.addGrade(92); + happyCohort.addStudent(s2); + // s2 average is 86.333333333333333 + + // cohort average is 70.67 + } + + @Test + public void testGetCohortAverage() { + assertEquals(0, emptyCohort.getCohortAverage(), 0.01); + assertEquals(70.67, happyCohort.getCohortAverage(), 0.01); + } + + @Test + public void testAddStudent() { + Student bob = new Student(3, "Bob"); + emptyCohort.addStudent(bob); + + // expect size to be 1 + assertEquals(1, emptyCohort.getStudents().size()); + // expect first student's id to be bob's id + assertEquals(bob.getId(), emptyCohort.getStudents().get(0).getId()); + + // now add bob to happyCohort and grab the middle student. the middle student + // should be S2 + happyCohort.addStudent(bob); + // check the size + assertEquals(3, happyCohort.getStudents().size()); + + // make sure s2 is now the middle student (index 1) + assertEquals(s2.getId(), happyCohort.getStudents().get(1).getId()); + } + + @Test + public void testGetStudentById() { + Student testStudent = happyCohort.getStudentById(s1.getId()); + + assertEquals(s1.getId(), testStudent.getId()); + assertEquals(s1.getName(), testStudent.getName()); + + testStudent = happyCohort.getStudentById(999999); + assertNull(testStudent); + + } + + @Test + public void testGetStudents() { + List tempStudents = emptyCohort.getStudents(); + assertEquals(0, tempStudents.size()); + + tempStudents = happyCohort.getStudents(); + assertEquals(2, tempStudents.size()); + assertEquals(s1.getId(), tempStudents.get(0).getId()); + assertEquals(s2.getId(), tempStudents.get(1).getId()); + } + +} diff --git a/src/test/java/students/StudentTest.java b/src/test/java/students/StudentTest.java new file mode 100644 index 00000000..22562e7e --- /dev/null +++ b/src/test/java/students/StudentTest.java @@ -0,0 +1,42 @@ +package students; + +import org.junit.Test; +import students.Student; + +import static org.junit.Assert.*; + +public class StudentTest { + @Test + public void testCreateStudent(){ + Student fer = new Student(1L, "fer"); + Student ryan = null; + assertNull(ryan); + assertNotNull(fer); + } + + @Test + public void testStudentFields(){ + Student fer = new Student(1L, "fer"); + assertSame(1L, fer.getId()); + assertSame("fer", fer.getName()); + assertSame(0, fer.getGrades().size()); + } + + + @Test + public void testAddGrade(){ + Student fer = new Student(1L, "fer"); + fer.addGrade(100); + assertSame(100, fer.getGrades().get(0)); + fer.addGrade(80); + assertSame(80, fer.getGrades().get(1)); + } + + @Test + public void testAverageGrade(){ + Student fer = new Student(1L, "fer"); + fer.addGrade(100); + fer.addGrade(80); + assertEquals(90, fer.getGradeAverage(), 0); + } +} \ No newline at end of file