1.4-Software-Development-Principles

Grading system

Introduction

We have a grading system that gets its data from an external source and writes the mean grade back to an external source. So now we have an indirect input source and an indirect output source. This makes it difficult for us to test the system.

Your task is to refactor the system so that we can test our grading system system.

The code for the grading system can be found in this zip file. We also provide an example csv file.

The code consists of three classes: Student, GradeReader and GradingSystem.

Student is a class to store the data about a student, including the grades. GradeReader reads the grade data from a file. GradingSystem is the program used to calculate the final grades, as show below. This is the logic that should be tested.

public class GradingSystem {
    private GradeReader gradeReader;

    public GradingSystem(GradeReader gradeReader) {
        this.gradeReader = gradeReader;
    }

    public void calculateFinalGrades() {
        // Read the grades from the file
        List<Student> students = gradeReader.readGrades();

        // Calculate the mean grade for each student
        for (Student student : students) {
            int sum = 0;
            for (int grade : student.getGrades()) {
                sum += grade;
            }
            int meanGrade = sum / student.getGrades().size();

            // Replace the student's grades with the mean grade
            student.getGrades().clear();
            student.getGrades().add(meanGrade);
        }

        // Write the final grades back to the file
        gradeReader.writeFinalGrades(students);
    }
}

Here’s an example of how you might write a unit test for this system:



public class GradingSystemTest {
    @Test
    public void testCalculateFinalGrades() {
        // Use the mock grade file for testing
        GradeReader reader = new GradeReader(...,...);
        GradingSystem system = new GradingSystem(reader);
        
        // Run the grading system and capture the output
        system.calculateFinalGrades();

        // Check that the output is as expected based on grades
        assertEquals("Expected Output",....);
    }
}

The problem is that we do not control the indirect input and cannot monitor the indirect output for the GradingSystem class. To make it possible to get control over this input we can make use of an interface. In the unit tests you can provide different implementations which will allow you to test the logic in the GradingSystem class.

Assignment 1

Refactor the system so that we can test our GradingSystem class. We want 100% line coverage on the GradingSystem class. Hint: Everything is now completed in one big operation where we have no access to any of the intermediate steps.

Assignment 2

The grading system can only read from CSV files. Add the possibility to also read grades from a JSON file and a database.