• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

artwork/H03-May-2022-65

debian/H07-May-2022-11480

doc/H03-May-2022-270187

git-hooks/H07-Jun-2019-178

include/H03-May-2022-385153

src/H03-May-2022-1,417878

test/H03-May-2022-15988

vendor/H07-Jun-2019-2,8161,133

website/H07-Jun-2019-

.gitignoreH A D07-Jun-201916 21

.gitmodulesH A D07-Jun-201992 43

.ycm_extra_conf.pyH A D07-Jun-2019744 2713

README.mdH A D07-Jun-20193.5 KiB146114

version.cmakeH A D07-Jun-201942 21

README.md

1# libgrading
2
3This is a simple library for grading C- and C++-language assignments.
4It runs each test case in a child process in order to capture common
5programming errors such as infinite loops and segmentation faults.
6
7## Get it
8
9libgrading is available as a binary package for FreeBSD, a Homebrew tap for
10macOS and a PPA for Ubuntu Linux.
11You can also build from source.
12
13### FreeBSD
14
15You can install a binary package with `pkg install libgrading`
16or compile the `devel/libgrading` port
17[from source](https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ports-using.html).
18
19### macOS
20
21First, install [Homebrew](https://brew.sh).
22Then, run
23`brew install trombonehero/homebrew-grading/libgrading`.
24
25### Ubuntu 18.04
26
27You can install a binary package from my
28[grading software PPA](https://launchpad.net/~professor-jon/+archive/ubuntu/grading-software):
29
30```terminal
31sudo add-apt-repository ppa:professor-jon/grading-software
32sudo apt-get update
33sudo apt install libgrading-dev
34```
35
36
37## Build it
38
39The libgrading source code is
40[hosted on GitHub](https://github.com/trombonehero/libgrading).
41Releases are available on
42[the GitHub releases page](https://github.com/trombonehero/libgrading/releases),
43and you can always get the most latest version by running either:
44
45~~~sh
46$ git clone https://github.com/trombonehero/libgrading.git
47$ svn checkout https://github.com/trombonehero/libgrading
48~~~
49
50First, install [libdistance](http://monkey.org/~jose/software/libdistance/).
51Then:
52
53~~~sh
54$ mkdir build
55$ cd build
56$ cmake ..       # or cmake -G Ninja ..
57$ make           # or ninja
58~~~
59
60## Use it
61
62~~~cpp
63#include <libgrading.h>
64using namespace grading;
65using namespace std;
66
67
68//
69// One way to define tests is to define a domain-relevant expectation
70// (inputs and outputs) and a function that will check that expectation:
71//
72struct AdditionExpectation
73{
74	int x;
75	int y;
76	int sum;
77};
78
79void TestStudentFn(const AdditionExpectation& expected)
80{
81	// In a real test suite, you'd link against submitted code.
82	// For this demo, we'll use a lambda.
83	auto studentFunction = [](int x, int y) { return x + y + 1; };
84
85	int sum = studentFunction(expected.x, expected.y);
86	CheckInt(expected.sum, sum)
87		<< "some more detail to be output if this check fails";
88}
89
90
91//
92// You can define a grading::TestSuite declaratively, if you like such things
93// (vs. using the TestBuilder class, as inside the `main` function below):
94//
95const TestSuite testClosures =
96{
97	// This is an example of a Test derived from an expectation and an
98	// evaluation function.
99	{
100		"simple addition test",
101		" - first part of the long description\n"
102		" - second part of the long description",
103		TestStudentFn,
104		{ 2, 2, 5 },
105		0,	// timeout: optional, 0 (the default) means forever
106		1,	// weight to give this test (optional, default 1)
107	},
108
109	// Tests can also be created from self-contained test closures:
110	{
111		"test name",
112		"long description ...",
113		[]()
114		{
115			int x = foo();
116			CheckInt(42, x)
117				<< "the result of calling foo() should be 42"
118				;
119
120			// segmentation faults will be caught and handled
121			// properly when running with --strategy=separated
122			// or --strategy=sandboxed (the default)
123			double *x = nullptr;
124			double y = *x;
125		},
126	},
127
128	// ...
129};
130
131
132//
133// You need to write a `main` function to actually run the tests,
134// but it can be very simple indeed:
135//
136int main(int argc, char *argv[])
137{
138	const TestSuite::Statistics stats = tests.Run(argc, argv);
139
140	// optionally do something with the stats, such as:
141	cout << "Grade: " << stats.score << endl;
142
143	return 0;
144}
145~~~
146