# Code grading examples

> CuraCourse Code Grading does not run unittest or JUnit. It runs a command in the sandbox and compares stdout to Expected Output.

Source: https://www.curacourse.com/help/code-grading-examples-python-and-java

## At a glance

CuraCourse **Code Grading** does not run unittest or JUnit. It runs a command in the sandbox and compares **stdout** to **Expected Output**.

When you add a hidden **grader** file, that file should do the checking and print:

- `PASS` when a check succeeds
- `FAILED` plus a short reason when it does not (what was called, what it got, what you expected)

Set **Expected Output** to one `PASS` line per check. Turn on **Show diff of actual output and expected output** so learners see the `FAILED` line. Use **Exact match**.

Whole programs with no grader file still compare printed output the usual way (Pattern A).

## Prerequisites

- A **Code Editor** activity with a **Code Grading** rubric item. See [Add rubric items (manual, AI, and code grading)](https://www.curacourse.com/help/add-rubric-items-manual-ai-and-code-grading).
- For hidden testers, use **Files** on the Code Grading item (not starter **Hidden Files**). Rubric files merge after the student submission, so a grader with a *new* filename will not overwrite student code. See [Best practices for code grading](https://www.curacourse.com/help/best-practices-for-code-grading).

## How to set up each example

1. Add **Code Grading** on the Code Editor.
2. Set **Run command** as shown in the example (it must compile/run the grader, not only the starter filename).
3. Fill **Input** only when the student program reads stdin. Put each value on its own line.
4. Paste **Expected Output**: for grader files, one `PASS` per check; for whole programs, the program’s printed text.
5. Optionally **Add File** for `grader.py` or `Grader.java`.
6. Click **Run Test** with a sample solution before you assign the lesson.

Do **not** name a rubric file the same as the student file (`main.py`, `Main.java`). Same path **replaces** the student file.

## Pattern A — Whole program (print / input)

Use this when students write a complete program. No extra grader file. Run their file and compare what it prints.

### Python: Hello World

**Run command:** `python3 main.py`

**Expected Output:**

```
Hello World
```

Student `main.py`:

```
print("Hello World")
```

### Java: Hello World

**Run command:** `javac Main.java && java Main`

**Expected Output:**

```
Hello World
```

Student `Main.java`:

```
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}
```

### Python: input and output

Students prompt for first and last name, then print `Hello, Jane Doe!`

**Run command:** `python3 main.py`

**Input** (one value per line):

```
Jane
Doe
```

**Expected Output** (prompts are part of stdout in Python):

```
What is your first name? Jane
What is your last name? Doe
Hello, Jane Doe!
```

If you only care about the greeting, turn on **Ignore Case** / **Ignore Whitespace**, or use **Partial match** with `Hello, Jane Doe!` as expected output. Add a second Code Grading item with different names (for example `Joe` / `Mazzone`) so they cannot hardcode one sample.

Student `main.py`:

```
fname = input("What is your first name? ")
lname = input("What is your last name? ")
print("Hello, " + fname + " " + lname + "!")
```

### Java: Scanner input and output

**Run command:** `javac Main.java && java Main`

**Input:**

```
Jane
Doe
```

**Expected Output** (Java `nextLine()` does not echo the typed text — match what *your* starter actually prints):

```
What is your first name?
What is your last name?
Hello, Jane Doe!
```

Student `Main.java`:

```
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("What is your first name?");
        String fname = in.nextLine();
        System.out.println("What is your last name?");
        String lname = in.nextLine();
        System.out.println("Hello, " + fname + " " + lname + "!");
    }
}
```

## Pattern B — Return values (hidden grader that prints PASS / FAILED)

Students write a **function/method** and do not need a `main`. You add a hidden grader that calls it, compares the result, and prints `PASS` or `FAILED`. CuraCourse only needs to match a list of `PASS` lines.

Starter should be only the function stub so importing/compiling it does not wait for input. The grader should print *only* `PASS` / `FAILED` lines — not the raw return values.

### Python: add_five

Students write `add_five(number)` that returns the argument plus 5.

**Run command:** `python3 grader.py`

**Files** → add `grader.py`:

```
from main import add_five

def check(label, actual, expected):
    if actual == expected:
        print('PASS')
    else:
        print('FAILED: ' + label + ' got ' + str(actual) + ', expected ' + str(expected))

check('add_five(5)', add_five(5), 10)
check('add_five(0)', add_five(0), 5)
check('add_five(6)', add_five(6), 11)
```

**Expected Output:**

```
PASS
PASS
PASS
```

If a student returns the wrong value, they see something like `FAILED: add_five(0) got 0, expected 5` in the diff.

Student `main.py`:

```
def add_five(number):
    return number + 5
```

### Java: addFive

Students write a class with `public static int addFive(int number)`.

**Run command:** `javac Main.java Grader.java && java Grader`

**Files** → add `Grader.java`:

```
public class Grader {
    static void check(String label, int actual, int expected) {
        if (actual == expected) {
            System.out.println("PASS");
        } else {
            System.out.println("FAILED: " + label + " got " + actual + ", expected " + expected);
        }
    }

    public static void main(String[] args) {
        check("addFive(5)", Main.addFive(5), 10);
        check("addFive(0)", Main.addFive(0), 5);
        check("addFive(6)", Main.addFive(6), 11);
    }
}
```

**Expected Output:**

```
PASS
PASS
PASS
```

Student `Main.java`:

```
public class Main {
    public static int addFive(int number) {
        return number + 5;
    }
}
```

### Python: average (five numbers → float)

Calling `average(1, 5, 7, 4, 10)` should return `5.4`. Compare with a small tolerance so float noise does not fail the check.

**Run command:** `python3 grader.py`

**Files** → `grader.py`:

```
from main import average

def check(label, actual, expected):
    if abs(actual - expected) < 0.001:
        print('PASS')
    else:
        print('FAILED: ' + label + ' got ' + str(actual) + ', expected ' + str(expected))

check('average(1, 5, 7, 4, 10)', average(1, 5, 7, 4, 10), 5.4)
check('average(5, 9, 24, 6, 4)', average(5, 9, 24, 6, 4), 9.6)
```

**Expected Output:**

```
PASS
PASS
```

Student `main.py`:

```
def average(a, b, c, d, e):
    return (a + b + c + d + e) / 5
```

### Java: average

**Run command:** `javac Main.java Grader.java && java Grader`

**Files** → `Grader.java`:

```
public class Grader {
    static void check(String label, double actual, double expected) {
        if (Math.abs(actual - expected) < 0.001) {
            System.out.println("PASS");
        } else {
            System.out.println("FAILED: " + label + " got " + actual + ", expected " + expected);
        }
    }

    public static void main(String[] args) {
        check("average(1, 5, 7, 4, 10)", Main.average(1, 5, 7, 4, 10), 5.4);
        check("average(5, 9, 24, 6, 4)", Main.average(5, 9, 24, 6, 4), 9.6);
    }
}
```

**Expected Output:**

```
PASS
PASS
```

Student `Main.java`:

```
public class Main {
    public static double average(int a, int b, int c, int d, int e) {
        int s = a + b + c + d + e;
        return (double) s / 5;
    }
}
```

### Python: has_repeat

Return `True` if a string contains the same letter twice in a row.

**Run command:** `python3 grader.py`

**Files** → `grader.py`:

```
from main import has_repeat

def check(label, actual, expected):
    if actual == expected:
        print('PASS')
    else:
        print('FAILED: ' + label + ' got ' + str(actual) + ', expected ' + str(expected))

check('has_repeat(mississippi)', has_repeat('mississippi'), True)
check('has_repeat(capsized)', has_repeat('capsized'), False)
check('has_repeat(mazzone)', has_repeat('mazzone'), True)
check('has_repeat(this)', has_repeat('this'), False)
```

**Expected Output:**

```
PASS
PASS
PASS
PASS
```

Student `main.py`:

```
def has_repeat(word):
    for i in range(len(word) - 1):
        if word[i] == word[i + 1]:
            return True
    return False
```

### Java: hasRepeat

**Run command:** `javac Main.java Grader.java && java Grader`

**Files** → `Grader.java`:

```
public class Grader {
    static void check(String label, boolean actual, boolean expected) {
        if (actual == expected) {
            System.out.println("PASS");
        } else {
            System.out.println("FAILED: " + label + " got " + actual + ", expected " + expected);
        }
    }

    public static void main(String[] args) {
        check("hasRepeat(mississippi)", Main.hasRepeat("mississippi"), true);
        check("hasRepeat(capsized)", Main.hasRepeat("capsized"), false);
        check("hasRepeat(mazzone)", Main.hasRepeat("mazzone"), true);
        check("hasRepeat(this)", Main.hasRepeat("this"), false);
    }
}
```

**Expected Output:**

```
PASS
PASS
PASS
PASS
```

Student `Main.java`:

```
public class Main {
    public static boolean hasRepeat(String str) {
        for (int i = 0; i < str.length() - 1; i++) {
            if (str.substring(i, i + 1).equals(str.substring(i + 1, i + 2))) {
                return true;
            }
        }
        return false;
    }
}
```

### Python: print function (void that prints)

Students write `print_hello()` that prints `Hello World` (it returns nothing). Capture that print, then emit `PASS` or `FAILED` — otherwise the student text would mix with the grader output.

**Run command:** `python3 grader.py`

**Files** → `grader.py`:

```
import io
import sys
from main import print_hello

def check(label, actual, expected):
    if actual == expected:
        print('PASS')
    else:
        print('FAILED: ' + label + ' got ' + repr(actual) + ', expected ' + repr(expected))

buf = io.StringIO()
old = sys.stdout
sys.stdout = buf
print_hello()
sys.stdout = old
check('print_hello()', buf.getvalue().strip(), 'Hello World')
```

**Expected Output:**

```
PASS
```

Student `main.py`:

```
def print_hello():
    print("Hello World")
```

## Pattern C — Classes (toString and void methods)

Construct the object in a hidden grader, compare `toString` / `__str__`, and capture anything void methods print so only `PASS` / `FAILED` reach stdout.

### Java: Employee

Students create `Employee` with name, 4-digit id, hourly salary, a constructor, `toString()` in the form:

```
John Doe -- 4545 -- $15.67 per hour
```

and `getRaise(double amount)` that increases salary and prints `Nice you got a $1.0 raise!`

**Run command:** `javac Employee.java Grader.java && java Grader`

**Files** → `Grader.java`:

```
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

public class Grader {
    static void check(String label, String actual, String expected) {
        if (actual.equals(expected)) {
            System.out.println("PASS");
        } else {
            System.out.println("FAILED: " + label + " got \"" + actual + "\", expected \"" + expected + "\"");
        }
    }

    public static void main(String[] args) {
        Employee e = new Employee("John Doe", 4545, 15.67);
        check("toString()", e.toString(), "John Doe -- 4545 -- $15.67 per hour");

        PrintStream original = System.out;
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        System.setOut(new PrintStream(buf));
        e.getRaise(1.0);
        System.setOut(original);
        check("getRaise(1.0) message", buf.toString().trim(), "Nice you got a $1.0 raise!");
        check("toString() after raise", e.toString(), "John Doe -- 4545 -- $16.67 per hour");
    }
}
```

**Expected Output:**

```
PASS
PASS
PASS
```

Add a second Code Grading item for another employee (for example `Bob Bobbington`, `5555`, `10.5`, raise `0.4`). Use a different grader filename per item, or one rubric item per test, so Files do not collide.

Sample student `Employee.java`:

```
public class Employee {
    private String name;
    private int id;
    private double salary;

    public Employee(String n, int i, double s) {
        name = n;
        id = i;
        salary = s;
    }

    public String toString() {
        return name + " -- " + id + " -- $" + salary + " per hour";
    }

    public void getRaise(double amount) {
        salary += amount;
        System.out.println("Nice you got a $" + amount + " raise!");
    }
}
```

Gotcha: `1.0` vs `1` in the raise message depends on how students print `amount`. If that is not part of the spec, skip the message check and only compare `toString()` after the raise.

### Python: same Employee idea

**Run command:** `python3 grader.py`

**Files** → `grader.py`:

```
import io
import sys
from main import Employee

def check(label, actual, expected):
    if actual == expected:
        print('PASS')
    else:
        print('FAILED: ' + label + ' got ' + repr(actual) + ', expected ' + repr(expected))

e = Employee('John Doe', 4545, 15.67)
check('str(employee)', str(e), 'John Doe -- 4545 -- $15.67 per hour')

buf = io.StringIO()
old = sys.stdout
sys.stdout = buf
e.get_raise(1.0)
sys.stdout = old
check('get_raise(1.0) message', buf.getvalue().strip(), 'Nice you got a $1.0 raise!')
check('str(employee) after raise', str(e), 'John Doe -- 4545 -- $16.67 per hour')
```

**Expected Output:**

```
PASS
PASS
PASS
```

Student `main.py`:

```
class Employee:
    def __init__(self, name, id, salary):
        self.name = name
        self.id = id
        self.salary = salary

    def __str__(self):
        return f"{self.name} -- {self.id} -- ${self.salary} per hour"

    def get_raise(self, amount):
        self.salary += amount
        print(f"Nice you got a ${amount} raise!")
```

## Partial credit

Each Code Grading item is all-or-nothing. Several `PASS` lines in one grader still succeed or fail together. To give “2 of 3 tests,” add three items (for example 1 point each), each with its own grader calls or stdin pair.

## Related articles

- [Add rubric items (manual, AI, and code grading)](https://www.curacourse.com/help/add-rubric-items-manual-ai-and-code-grading)
- [Best practices for code grading](https://www.curacourse.com/help/best-practices-for-code-grading)
- [Course blocks: code editor library](https://www.curacourse.com/help/course-blocks-code-editor-library)

