dscpsyl / jgrade2

An update to the original jGrade for Java 17 and jUnit 5
https://dscpsyl.github.io/jgrade2/javadoc
MIT License
2 stars 1 forks source link

Contributors Forks Stargazers Issues MIT License LinkedIn

jGrade2

An annotation library used to help autograde student assignments in Java for Gradescope.
Explore the docs »

Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Contributing
  5. License
  6. Acknowledgments

About The Project

This repo is now behind. Please visit the new organization and Github repo for jGrade 2

This is an update to the original jGrade, now supporting Java17 and JUnit5. This provides four annotations: @Grade (+ @BeforeGrading and @AfterGrading) and @GradedTest, each meant to help autograde student assignments in Java for the Gradescope autograder. When correctly setup, instructors can simply use JUnit5 to write tests for assignemnts. This library will automatically capture results, and output the correct json format for Gradescope to read.

(back to top)

Getting Started

Prerequisites

jGrade2 requires Java 17 and JUnit5. It is recommended to use Maven to manage dependencies. Additional dependencies are listed in the pom.xml file. For the user's convenience, a jar file is provided containing all the dependencies.

Installation

There are two ways to install jGrade2.

  1. Install directly from GitHub releases. You can download either jar files or build the source code from scratch. If building from source, this project uses maven wrapper to build. Simply run ./mvnw clean package to build the project. Two jar files will be created, both reflected on the releases page.
  2. Add as a dependency directly from Maven Central.
<dependency>
  <groupId>io.github.dscpsyl</groupId>
  <artifactId>jgrade2</artifactId>
  <version>${jGrade2.version}</version>
</dependency>

(back to top)

Usage

Usage is nearly identical to the origional jGrade. jGrade2 comes with a commandline to run the grader manually. This is useful for debugging and testing. After compiling, you can use

java -jar jGrade2.jar -h

for help and options of the commandline. However, a typical usage would be

java -jar jGrade2.jar -c ExampleGrading -o results.json

Test Writting and Grading

You can take a look at the gradescope example in examples/gradescope for a full example.

Tests

Tests are written in jUnit5. The only addition will be the @GradedTest annotation to each test that should be counted in the assignment on gradescope.

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
import com.github.dscpsyl.jgrade2.gradedtest.GradedTest;

import static com.github.dscpsyl.jgrade2.gradedtest.HIDDEN;
import static com.github.dscpsyl.jgrade2.gradedtest.VISIBLE;

public class ExampleTest {
    @Test
    @GradedTest(name="Example Test", points=10)
    public void testExample() {
        Assertions.assertTrue(true);
    }

    @Test
    @GradedTest(name="Hidden Test", points=10, visibility=HIDDEN)
    public void testHidden() {
        Assertions.assertTrue(true);
    }

    @Test
    @GradedTest(name="Visible Test", number="4", points=10, visibility=VISIBLE)
    public void testVisible() {
        Assertions.assertTrue(true);
    }

}

The @GradedTest annotation has the following parameters:

Grading

Grading is done by a simple grading class. This class should be in the same package as the tests. Each method in the grading class that should be considered for grading needs to be annotated with @Grade. The method should take in a single parameter of type Grader. @BeforeGrading and AfterGrading can be used to run code before and after grading respectively. These methods should also take in a single parameter of type Grader.

import com.github.dscpsyl.jgrade2.Grader;
import com.github.dscpsyl.jgrade2.GradedTestResult;

import com.github.dscpsyl.jgrade2.Grade;
import com.github.dscpsyl.jgrade2.AfterGrading;
import com.github.dscpsyl.jgrade2.BeforeGrading;

import static com.github.dscpsyl.jgrade2.gradedtest.HIDDEN;

public class ExampleGrading {

  /* This function will run before grading starts*/
  @BeforeGrading
  public void beforeGrading(Grader g) {
    System.out.println("Starting grading");
    grader.startTimer();
  }

  /* You can grade a full test class that is in the same package as this class */
  @Grade
  public void gradeTestClass(Grader g) {
    g.runJUnitGradedTests(ExampleTest.class);
  }

  /* If you cannot use jUnit5 or java to grade, you can manually add results */
  @Grade
  public void gradeManually(Grader g) {
    g.addGradedTestResult(new GradedTestResult("Manual Test", "4" , 10.0, HIDDEN));
  }

  /* Grader.startTimer() and Grader.stopTimer() can be used to time the grader */
  @Grade
  public void loopForTime(Grader grader) {
    long startTime = System.currentTimeMillis();
    while (System.currentTimeMillis() - startTime < 1000);
  }

  /* @AfterGrading methods are run after all other methods. */
  @AfterGrading
  public void endGrader(Grader grader) {
    grader.stopTimer();
    System.out.println("Grading finished");
  }

}

Gradescope Setup

There is a full example in examples/gradescope that works on gradescope, and models much of the setup from the original java example Gradescope links to.

It compiles all files in to a created classes/ directory (not tracked). All the scripts will be looking for your classes in this directory.

The lib/ folder contains all jars and library files needed to run your test - for this example just the jGrade2 jar file (optionally a checkstyle jar for the checkstyle grading method). The res/ directory is for resources (like the checkstyle configuration file).

src/ is the main source code of both your grading code and your tests.

test_submissions/ are submissions to test with on Gradescope. These are precompiled for you to test with the grader that is included in the example.

The source has 2 main packages, staff and student. The staff package contains the unit tests, a solution (to debug with) and the code to do the grading. The student package contains studnet skeleton code for studnets to fill in.

While debugging, a makefile is provided for compiling and running. make output will start fresh and run the autograder, pretty-printing the output to the console.

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

The repository is structured like so:

Other branches are for personal developnment and should only be pulled to the dev branch. Once a release is determined, then a pull request can be made to main or master.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

License

Distributed under the MIT License. See LICENSE.txt for more information.

(back to top)

Acknowledgments

(back to top)