- Automated testing for command-line projects in GitHub Classroom
maketest
can clone repos, build them, run with predetermined input and output, and score the results vs. your rubric- To get started, clone
maketest
onto your machine andcd
into it
- Student projects must be callable from the command line, and write results to
stdout
or another file you specify (seealtactual
below) - Student projects must have a
Makefile
to build them - The
Makefile
must generate an executable with the same name as thePROJECT
(see below) - If written in C, your projects must take input via
argc
andargv
, not viastdin
- You must use GNU
make
4.2 or later. This is current on Raspberry Pi OS, but macOS installsmake
3.6 by default. If you're running this on macOS, you might need tobrew install make
but I haven't testedmaketest
on macOS
- Remember to run the
maketest
commands from themaketest/
directory - You may want to use the
make
flags-s
(silent) and-k
(keep going past errors). You can combine the flags, e.g.make -ks
maketest
expects to findmake
variables forORG
andPROJECT
as they are shown in GitHub Classroom. In this README I use examples from the Spring 2020 class but you should substitute theORG
andPROJECT
values for your class. You can specify these variables in one of three places, based on your preference- On the command line
make -ks test ORG=cs315-20s PROJECT=project02
- In the
Makefile
by editing the variables manuallymake -ks test
- In your shell environment (or
.bashrc
). You can use the-e
flag to tellmake
to get its variables from the environmentexport ORG=cs315-20s PROJECT=project02 STUDENTS="phpeterson-usf gdbenson" make -eks test
- On the command line
- In addition to the
ORG
andPROJECT
variables, students must define aDIR
variable which contains the local filesystem path to your project - To test your local repo (without cloning)
make -ks PROJECT=project04 DIR=../project04-phpeterson-usf
- You should see output which looks like this
build: ../project04-phpeterson-usf/ run: ../project04-phpeterson-usf/ PASS for: -f quadratic -a 2,4,8,16 run: ../project04-phpeterson-usf/ PASS for: -f fib_iter -a 20 run: ../project04-phpeterson-usf/ FAIL for: -f find_max -a 2,-4,28,16 score: ../project04-phpeterson-usf/ 10
- To test the project with a new/clean repo (as the instructor will), you can run the
clone
andtest
targetsmake -ks clone test PROJECT=project04 ORG=cs315-20s STUDENTS=phpeterson-usf
- In addition to the
ORG
andPROJECT
variables, instructors must defineSTUDENTS
which contains a list of students' GitHub IDs. You may wish to do that in theMakefile
or your environment, since the long list is static throughout the school term. - To clone all the student repos, use the
clone
target (assuming your are logged in to GitHub Classroom as a teacher for the Organization)make -ks clone ORG=cs315-20s PROJECT=project02 STUDENTS="phpeterson-usf gdbenson"
- To build, run, test, and score the repos, use the
test
target (pro tip:test
is the default target so you can omittest
if you like)make -ks test ORG=cs315-20s PROJECT=project02 STUDENTS="phpeterson-usf gdbenson"
- To pull new changes since you cloned the repos, use the
pull
targetmake -ks pull ORG=cs315-20s PROJECT=project02 STUDENTS="phpeterson-usf gdbenson"
- To checkout changes at a timestamp, use the
checkout
target with aDATE
make -eks checkout DATE="'main@{2020-08-25 00:00:00}'"
- When you run the test cases for your
project02
solutionmake -ks test PROJECT=project02 DIR=../project02-phpeterson-usf
maketest
will generate a.actual
file for each test case and one.score
file in your directory. - To get credit for passing a test case, your output must match the expected output. Case and
whitespace are not significant (it's
diff -b -i
) - The overall project rubric contains some portion for automated testing. The
automated testing portion of the rubric is the sum of the scores in the
.score
file - Since a clean repo does not contain build artifacts (like your
.o
files), you should not commit.actual
or.score
files to your repo. You may wish to remove them before committingAlternatively,rm *.actual *.score
maketest
can remove them using theclean
targetmake -ks clean PROJECT=project02 DIR=../project02-phpeterson-usf
- In
maketest/tests/
you should create a directory for eachPROJECT
- In each
PROJECT
directory, you should create test cases. A test case is defined by three text files. For test casefoo
, you should create:foo.input
containing the command line arguments (not including the executable name) you wish to test. The format of the arguments is up to you, but students must parse the format you specify. I'm usinggetopt
style arguments-f quadratic -a 1,2,3,4
foo.expected
containing the output you expect forfoo.input
foo.rubric
containing the number of points earned when the student'sfoo.actual
output matches (viadiff -i
) yourfoo.expected
- If your project writes output to a different file other than
stdout
, you can specify that file in the contents offoo.altactual
maketest
is itself aMakefile
and everything it does is a list of targets- The approach is to build lists of unique target names using a unique suffix for each phase (clone, pull, clean, build, run, score)
- There is a target for each test case for each phase for each student, so the target lists are pretty long
- However, since
make
loops over the target lists automatically, the recipes for each phase can be relatively simple - There is a log file in
./$(PROJECT).log
with all the gory details. Can be useful for finding bugs, either mine or the students!