Example - C++ Library#

An example for an exam, where the interface is defined in the .h file and the student implements the .cpp file.

Exercise:

For a given non-zero whole number N return the factorial of N (1 * 2 * 3 * ... N)

Example .h file:

#ifndef Q_H
#define Q_H

// DO NOT MODIFY THIS FILE!
// THIS FILE DEFINES THE STRUCTURE OF THE FUNCTIONS WHICH WILL BE TESTED
// IF YOU MODIFY THE STRUCUTRE OF THE FUNCTION, YOUR RESULTS WILL NOT BE VALID

// API: For a given non-zero whole number N return the factorial of N (1 * 2 * 3 * ... N)
// if N is 0, return 1
// Params:
//  N - the number to calculate factorial for (n <= 20)
// Returns:
//  The factorial of the number
// Example:
//  N - 5, return - 120
unsigned long long factorial(int N);

#endif // Q_H

Example empty .cpp file:

#include "Maths.h"

// import any required libraries here

unsigned long long factorial(int N){

}

Example solved .cpp file:

#include "Maths.h"

// import any required libraries here

unsigned long long factorial(int N){
    if(N <= 1){
        return 1;
    }
    return N * factorial(N - 1);
}

Example tester:

#include "Maths.h"
#include "cpp_eval_util.h"
#include <string>
#include <iostream>
#include <exception>

using namespace std;

#define TEST_CASE_COUNT 8

class FactorialEvaluator : public Evaluator<unsigned long long> // Change this type to the type returned by the evaluated function
{
  public:
    // Test cases
    unsigned long long test_cases[TEST_CASE_COUNT][2] = {
        {0, 1},
        {1, 1},
        {2, 2},
        {5, 120},
        {10, 3628800},
        {12, 479001600},
        {15, 1307674368000},
        {20, 2432902008176640000}
    };

    // Constructor
    FactorialEvaluator(int argc, char** argv):Evaluator(argc, argv){}

    // Return the name of the exam. Evaluator will start at i = 0 until "" is returned, which marks the number of questions.
    string GetName(int i){
      if(i >= TEST_CASE_COUNT) { return ""; }
      return "factorial(" + to_string(test_cases[i][0]) + ")";
    }

    // For a given question run some code. Return value must match Evaluator<> templated type
    unsigned long long GetResult(int i){
      return factorial(test_cases[i][0]);
    }

    // For a given result, return a score between 0 and 1. Second parameter type must match Evaluator<> templated type
    float GetScore(int i, unsigned long long result){
      return result == test_cases[i][1] ? 1.0f : 0.0f;
    }

    // For a given result and score, return some feedback. Second parameter type must match Evaluator<> templated type
    string GetFeedback(int i, unsigned long long result, float score){
      return "Returned " + to_string(result) + ", expecting " + to_string(test_cases[i][1]) + (score >= 1 ? " : PASS!" : " : FAIL!");
    }
};

int main(int argc, char **argv) {
  FactorialEvaluator evaluator(argc, argv);
  return evaluator.Run();
}

Example config file:

{
    "tests": [
        {
            "type": "replace_files",
            "files": [
                "C++/2_Advanced/02_Maths/Maths.h"
            ]
        },
        {
            "type": "compile",
            "max_score": 10.0,
            "number": "1",
            "tags": [],
            "visibility": "visible"
        },
        {
            "type": "functionality",
            "max_score": 60.0,
            "number": "2",
            "tags": [],
            "visibility": "visible",
            "tester_file": "path/to/factorial_tester.cpp"
        },
        {
            "type": "static",
            "max_score": 10.0,
            "number": "3",
            "tags": [],
            "visibility": "visible"
        },
        {
            "type": "comments",
            "max_score": 10.0,
            "number": "4",
            "tags": [],
            "visibility": "visible"
        },
        {
            "type": "style",
            "max_score": 10.0,
            "number": "5",
            "tags": [],
            "visibility": "visible",
            "style": "google"
        }
    ]
}

More than one tester can be used to test multiple functions