pengtest

Test suite tools for instructors


License
GPL-3.0
Install
pip install pengtest==0.9.9.6.1

Documentation

PengTest - The Python Instructional Test Suite System

Team Peng - CIS 4930 - Python Term Project
- Tyler Maiello
- Emma Andrews
- Matthew Baumaister
- Matthew McDermott
- Gerard Avecilla

GitHub Link: https://github.com/tmaiello/pengtest

PIP Installation Command: python3 -m pip install .

PIP Installation name: pengtest

This test suite it built to facilitate testing of student projects by teachers according to a predefined specification.

This package includes five primary tools:

  • pengtest.toolbox, which contains standardized / cross-platform function calls (currently only library loading)
  • elma, a command line tool to extract student submissions: (E)xtract (LM)S (A)rchive. Support is limited to Canvas.
  • peng, a command line tool to run a project test suite as specified by the user.
  • peng-gui, a graphical interface built on top of the other command-line tools in this package.
  • csv-upload, a CLI tool to automatically push a well formatted CSV of student grades and comments to a specified assignment.
  • peng-canvas, a CLI tool to automatically push a test suite results summary CSV to a Canvas assignment. Also has the ability to pull submissions from a selected assignment.
  • moss, a CLI tool to run Stanford Moss similarity checking on student submissions

PengTest Toolbox (pengtest.toolbox)

The toolbox includes the following helper functions, intended to be cross-platform:

loadTempLibrary(directory, name) Returns library loaded with temporary filename; this is necessary on some systems to avoid name collisions.

loadLibrary(directory, name) Returned regularly loaded library

unloadLibrary(library) Unloads the library passed as a parameter

findLibrary(directory, name) Attempts to find any valid version of the library, name-wise (lib, so, etc)

loadModule(filename) Loads a Python module from the supplied filename and returns it.

Extracting LMS Archives (elma)

The 'elma' tool will extract a mass-download archive file from LMS systems (such as Canvas) to a submissions directory, accounting for common renaming schemes and potential student name collisions.

usage: elma [-h] FILENAME DESTINATION

Running Unit Test Suite (peng)

The peng command will begin the running of unit tests of all target project. It can take the following arguments:

usage: peng [-h] [-V] [-q] [-d] [suite_path] [target_path]

positional arguments: suite_path path of test suite to load (default: ./) target_path path of the target projects to consider (by subdirectory / folder) (default: Projects)

optional arguments:

-h, --help show this help message and exit

-V, --version show program's version number and exit

-q, --quiet execute in quiet mode (default: False)

-d, --debug display debug information (default: False)

(currently limited to library loading / execution)

Upon startup, the peng utility will optionally initialize the framework specified in the settings. This framework is only built and initialized once for all students; any items that must be rebuilt for each student should be handled on an per-subject (student) basis. The peng utility provides a mechanism to initialize and clean up at the framework, subject, and project level (where there is one framework used to test many subjects, and each subject has one or more projects that are tested individually.)

The test suite is identified by a "config.py" file that is loaded as a module. The config file must provide the following interface to the testing system:

--project submodule object (config.project)

--build namespace object (config.build)

These objects are further described below.

Project Submodule

The project submodule should provide the following interface to the testing system:

Variables

projectPenalties List of ordered pairs representing overall project test penalties (such as for execution time). Overall penalties are tested for only once for an entire project, rather than for each individual data test case. List is formatted as: [ ( str:"PenaltyName", float:MAX_PENALTY )* ]

If projectPenalties is empty or "None", this has no effect. (Note that the project penalties listed must be supported by the testing functions below.)

testCasePenalties List of ordered pairs representing penalties applied to individual test cases. These are tested for each data test case. List is formatted as: [ ( str:"PenaltyName", float:MAX_PENALTY )* ]

If testCasePenalties is empty or "None", this has no effect. (Note that the case test penalties listed must be supported by the testing functions below.)

maxPenalty This value identifies the maximum fraction of the grade that can be reduced due to penalties overall. 0.0 would mean no penalties will be assessed, while 1.0 would mean students could lose all credit potentially.

projects A list of projects to be tested for each subject (student). Project list is in the following format: [ ( str:"display name", str:"internal name", float:POINT_VALUE )+ ]

The display name is used in output about project testing, while the internal name is passed to the initializeProject function outlined below. The point value identifies how the project should be scored.

Functions

Initialization / Shutdown of Test Suite

initializeFramework(framework_bin) This function is called after building the framework. It is passed the framework output (binary) directory. It should return any framework_context that is important to properly shutdown / cleanup the framework.

shutdownFramework(framework_context) This function will be called when all testing is done in order to shutdown / clean up the framework. The context passed in is identical to that returned by the initializeFramework function.

initializeSubject(subject_bin) This function is called after the subject project(s) are built but before they are tested. It is passed the subject output (binary) directory. It should return any subject_context that is important to properly shutdown / cleanup once all of the subject's project tests have been completed.

shutdownSubject(subject_context) This function will be called when all testing is done for this subject. The subject_context passed in is identical to that returned by the initializeSubject function.

initializeProject(identifier, framework_context, subject_context, config.project) This function is called by the test suite to prepare a project to be tested. It includes the project's internal string identifier as well as the framwork / subject contexts (returned by the initializers) and the project settings. Is should return any project_context that is important to properly shutdown / cleanup the project after testing is done.

shutdownProject(project_context) This function will be called when all testing is done for this project. The project_context passed in is identical to that returned by the initializeProject function.

Testing Functions

getNumberOfTests(project_context) Returns the number of data test cases available for the project identified by project_context.

getTestDescription(test_number, project_context) Returns a string describing the test identified by test_number and project_context.

runCaseTest(test_number, project_context) Runs the test identified by test_number and project_context, returning a score.

runCasePenalty(penalty_number, test_number, project_context) Runs the test identified by test_number and project_context, capturing the penalty identified by penalty_number.

runProjectPenalty(penalty_number, project_context) Runs the penalty test identified by penalty_number and project_context, returning its value.

analyzeRunLog(location) Analyzes the run.log returned from the VM, returning a string containing the values to add to the csv and the total score.

Build Namespace

The build namespace objects holds paths and build commands. It must provide the following interface:

base (string) Path to the base project source files; these will be copied into the target before the subject (student) submission files are copied.

destination (string) Path where student files should be copied. Usually inside the subject_src directory (see subject_src).

resources (string) Path to resources used by the project (if any; may be None)

subject_src (string) Path to source files for the target / subject project to be built. Usually contains the destination directory.

subject_bin (string) Path in which the subject project will be built

framework_src (string) Path to source files for the framework used for testing the projects

framework_bin (string) Path in which the framework will be built

prep_cmd (list of strings) Command to be used to prepare the build (e.g., autoconf or cmake). This is a list of strings consisting of the command followed by its arguments.

compile_cmd (list of strings) Command to be used to compile the build (e.g., make or devenv). This is a list of strings consisting of the command followed by its arguments.

Building & Running Graphical Interface (peng-gui)

To run the GUI from WSL2, VcXsrv should be running first.

Some additional OS packages may be required (especially on stock distributions of WSL2):

sudo apt install libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xfixes0 libxcb-xinerama0

Using The CSV Uploading Tool (csv-upload)

To run from CLI after building peng, run csv-upload with optional flags --help, --version, and --setupenv

Where --setupenv will run you through the installation process of importing your Canvas API Token.

Using The Push/Pull Tool (peng-canvas)

To run from CLI after building peng, run peng-canvas with optional flags --help, and --setupenv

Where --setupenv will run you through the installation process of importing your Canvas API Token.

Using the Stanford Moss Integration Tool (moss)

To run the Standford Moss similarity checker through PengTest, invoke command moss with required positional argument of language, and optional (assumes local ./basefiles and ./submissions if not provided) basefiles (code provided to students) and submissions (student submissions)

Includes optional flag --setupenv

Where --setupenv will run you through the installation process of importing your Canvas API Token.

Building this Package

To build package: python3 setup.py sdist bdist_wheel

To upload: python3 -m twine upload dist/*