| Title: | 'roxygen2'-Style Metadata for Test Cases and Function Documentation |
|---|---|
| Description: | Extends 'roxygen2' to support '@meta' tags for documenting 'testthat' test cases and function specifications. Includes a custom 'JUnit' reporter that exports test metadata as XML properties and validation functions to ensure all exported functions and tests contain required tags. Designed for traceability between requirements and tests in regulated industries such as pharma and finance. |
| Authors: | Moritz Lang [aut, cre], Mario Annau [aut], Doug Kelkhoff [ctb], Szymon Maksymiuk [ctb] |
| Maintainer: | Moritz Lang <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 1.3.0 |
| Built: | 2026-07-15 20:46:32 UTC |
| Source: | https://github.com/cran/roxyreqs |
A suite of functions to validate metadata documentation in Rd and test files.
Meta tags follow the format @meta key value where key can be any
user-defined identifier. Built-in tags for function documentation include
id, compliance_risk, and implementation_complexity. For test files,
the default required tags are author, reviewer, review_date, and
description. Custom tags can be added and validated by passing them to
the check_rd_tag_exist or check_test_tag_exist parameters.
This function combines multiple checks to ensure metadata in your Rd and test files meets required standards for completeness, uniqueness, and documentation quality. The following checks are included:
check_meta_rd(): Checks for missing metadata tags in Rd files.
check_meta_unique_ids(): Ensures the 'Id' metadata tag in Rd files is unique.
check_meta_undocumented_test(): Validates that all test_that test cases
are properly documented.
check_meta_test(): Verifies that test case documentation contains all required
metadata tags.
check_meta( files_rd = list.files("man", pattern = "*.Rd", full.names = TRUE), files_test = list.files("tests/testthat", pattern = "^test-.*\\.R$", full.names = TRUE), check_rd_tag_exist = c("Id", "Compliance Risk", "Implementation Complexity", "Test Scope"), check_test_tag_exist = c("author", "reviewer", "review_date", "description"), check_rd_tag_unique = "Id", exclude_package_rd = TRUE, concise = TRUE, print_error = FALSE ) check_meta_test( files_test = list.files("tests/testthat", pattern = "^test-.*\\.R$", full.names = TRUE), check_test_tag_exist = c("author", "reviewer", "review_date", "description"), concise = FALSE, print_error = FALSE ) check_meta_undocumented_test( files_test = list.files("tests/testthat", pattern = "^test-.*\\.R$", full.names = TRUE), concise = FALSE, print_error = FALSE ) check_meta_rd( files_rd = list.files("man", pattern = "*.Rd", full.names = TRUE), check_rd_tag_exist = c("Id", "Compliance Risk", "Implementation Complexity", "Test Scope"), exclude_package_rd = TRUE, concise = FALSE, print_error = FALSE ) check_meta_unique_ids( files_rd = list.files("man", pattern = "*.Rd", full.names = TRUE), check_rd_tag_unique = "Id", exclude_package_rd = TRUE, concise = FALSE, print_error = FALSE )check_meta( files_rd = list.files("man", pattern = "*.Rd", full.names = TRUE), files_test = list.files("tests/testthat", pattern = "^test-.*\\.R$", full.names = TRUE), check_rd_tag_exist = c("Id", "Compliance Risk", "Implementation Complexity", "Test Scope"), check_test_tag_exist = c("author", "reviewer", "review_date", "description"), check_rd_tag_unique = "Id", exclude_package_rd = TRUE, concise = TRUE, print_error = FALSE ) check_meta_test( files_test = list.files("tests/testthat", pattern = "^test-.*\\.R$", full.names = TRUE), check_test_tag_exist = c("author", "reviewer", "review_date", "description"), concise = FALSE, print_error = FALSE ) check_meta_undocumented_test( files_test = list.files("tests/testthat", pattern = "^test-.*\\.R$", full.names = TRUE), concise = FALSE, print_error = FALSE ) check_meta_rd( files_rd = list.files("man", pattern = "*.Rd", full.names = TRUE), check_rd_tag_exist = c("Id", "Compliance Risk", "Implementation Complexity", "Test Scope"), exclude_package_rd = TRUE, concise = FALSE, print_error = FALSE ) check_meta_unique_ids( files_rd = list.files("man", pattern = "*.Rd", full.names = TRUE), check_rd_tag_unique = "Id", exclude_package_rd = TRUE, concise = FALSE, print_error = FALSE )
files_rd |
character; A vector of paths to |
files_test |
character; A vector of paths to test files to be checked. |
check_rd_tag_exist |
character; A vector of metadata tag names in Rd files to check for completeness. |
check_test_tag_exist |
character; A vector of metadata tag names in test files to check for completeness. |
check_rd_tag_unique |
character; A single metadata tag in Rd files to check for uniqueness.
Default is |
exclude_package_rd |
logical; Whether to exclude package-level Rd files (i.e., files ending
with |
concise |
logical; Whether to print only failures instead of detailed output. Default is
|
print_error |
logical; Whether to print error messages. This is useful for CI/CD pipelines
to produce errors when issues are found. Default is |
check_meta(): A named list with results from each sub-check
(invisibly).
Id: URS01.FS005
Compliance Risk: low
Implementation Complexity: low
Test Scope: low
This reporter includes detailed results about each test and summaries, written to a file (or stdout) in JUnit XML format. This can be read by the Jenkins Continuous Integration System to report on a dashboard etc. Requires the xml2 package.
To fit into the JUnit structure, context() becomes the <testsuite>
name as well as the base of the <testcase> classname. The
test_that() name becomes the rest of the <testcase> classname.
The deparsed expect_that() call becomes the <testcase> name.
On failure, the message goes into the <failure> node message
argument (first line only) and into its text content (full message).
Execution time and some other details are also recorded.
Tests without @meta roxygen blocks produce test cases with an
empty <properties/> node. Use check_meta_test() to validate
that all required tags are present.
References for the JUnit XML format: http://llg.cubic.org/docs/junit/
testthat::Reporter -> testthat::JunitReporter -> JunitReporterMeta
resultsTest results.
timerProcess time tracker.
docXML document object.
errorsError count for current suite.
failuresFailure count for current suite.
skippedSkip count for current suite.
testsTest count for current suite.
rootXML root node (<testsuites>).
suiteCurrent XML suite node (<testsuite>).
suite_timeElapsed time for current suite.
file_nameCurrent test file path.
roxy_blocksParsed roxygen2 blocks for current file.
testthat::Reporter$.start_context()testthat::Reporter$cat_line()testthat::Reporter$cat_tight()testthat::Reporter$end_context_if_started()testthat::Reporter$end_file()testthat::Reporter$end_test()testthat::Reporter$initialize()testthat::Reporter$is_full()testthat::Reporter$local_user_output()testthat::Reporter$rule()testthat::Reporter$update()elapsed_time()
Return elapsed time since last call and reset timer.
JunitReporterMeta$elapsed_time()
Elapsed time in seconds.
reset_suite()
Reset suite counters to zero.
JunitReporterMeta$reset_suite()
start_reporter()
Initialize the reporter, create XML document.
JunitReporterMeta$start_reporter()
start_file()
Start processing a test file. Parses roxygen2 blocks.
JunitReporterMeta$start_file(file)
filePath to the test file.
start_test()
Called at the start of each test.
JunitReporterMeta$start_test(context, test)
contextTest context name.
testTest name.
start_context()
Start a new test suite context.
JunitReporterMeta$start_context(context)
contextContext name.
end_context()
Finalize a test suite context. Writes counts and time.
JunitReporterMeta$end_context(context)
contextContext name.
add_result()
Add a test result. Matches @meta tags from roxygen2
blocks and writes them as XML properties.
JunitReporterMeta$add_result(context, test, result)
contextContext name.
testTest name.
resultA testthat expectation object.
end_reporter()
Write the XML document to the output destination.
JunitReporterMeta$end_reporter()
clone()
The objects of this class are cloneable with this method.
JunitReporterMeta$clone(deep = FALSE)
deepWhether to make a deep clone.
Id: URS01.FS007
Compliance Risk: low
Implementation Complexity: medium
Test Scope: medium
## Not run: testthat::test_local(path = "inst/example.pkg", reporter = JunitReporterMeta) ## End(Not run)## Not run: testthat::test_local(path = "inst/example.pkg", reporter = JunitReporterMeta) ## End(Not run)
S3 methods that extend roxygen2 to support @meta tags in function and
test documentation. Tags follow the format @meta key value where key
can be any user-defined identifier (underscores become spaces, title-cased
in output).
## S3 method for class 'roxy_tag_meta' roxy_tag_parse(x) ## S3 method for class 'roxy_tag_meta' roxy_tag_rd(x, base_path, env) ## S3 method for class 'rd_section_meta' merge(x, y, ...) ## S3 method for class 'rd_section_meta' format(x, ...)## S3 method for class 'roxy_tag_meta' roxy_tag_parse(x) ## S3 method for class 'roxy_tag_meta' roxy_tag_rd(x, base_path, env) ## S3 method for class 'rd_section_meta' merge(x, y, ...) ## S3 method for class 'rd_section_meta' format(x, ...)
x |
A roxygen2 tag, rd_section, or Rd object depending on the method. |
base_path |
Base path of the package (used by roxygen2 dispatch). |
env |
Package environment (used by roxygen2 dispatch). |
y |
A second rd_section_meta object to merge with |
... |
Additional arguments passed to methods. |
format.rd_section_meta automatically computes a Test Scope value from
Compliance Risk and Implementation Complexity using an internal
scopemap matrix. Tags are reordered with Id, Compliance Risk,
Implementation Complexity, and Test Scope first, followed by any
custom tags.
Id: URS01.FS011
Compliance Risk: low
Implementation Complexity: low
Test Scope: low
Move macro (meta) fragment right after arguments
move_macro_first(x, rd_tag = "\\title", offset = 1L)move_macro_first(x, rd_tag = "\\title", offset = 1L)
x |
An Rd object as returned by |
rd_tag |
character; Rd tag name after which macro section shall be moved |
offset |
integer; Offset index, so that macro block is moved after rd_tag plus following text. |
transformed Rd object
Id: URS01.FS012
Compliance Risk: low
Implementation Complexity: low
Test Scope: low
Parse Metadata from Rd Files
parse_rd_meta(filepath)parse_rd_meta(filepath)
filepath |
Character array specifying paths to Rd-files. |
data.frame containing one column for each meta tag and one row per filepath.
Id: URS01.FS006
Compliance Risk: low
Implementation Complexity: low
Test Scope: low