Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
- 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.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<artifactId>tests</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
Expand Down
45 changes: 45 additions & 0 deletions src/main/java/students/Cohort.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package students;

import java.util.ArrayList;
import java.util.List;

public class Cohort {

private List<Student> 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<Student> getStudents() {
return students;
}
}
40 changes: 40 additions & 0 deletions src/main/java/students/Student.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package students;

import java.util.ArrayList;

public class Student {

private long id;
private String name;
private ArrayList<Integer> 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<Integer> 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() ;
}
}
87 changes: 87 additions & 0 deletions src/test/java/students/CohortTest.java
Original file line number Diff line number Diff line change
@@ -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<Student> 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());
}

}
42 changes: 42 additions & 0 deletions src/test/java/students/StudentTest.java
Original file line number Diff line number Diff line change
@@ -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);
}
}