ARCExpect
Introduction
ARCExpect
offers easy to use and understand APIs to create and execute validation cases. The main intention of this library is offering a framework for validation of ControlledVocabulary tokens in Research Data management (RDM) based on testing principles from the world of software development:
- a
validation case
is the equivalent of a unit test Validate.*
functions are the equivalent ofAssert.*
,Expect.*
, or equivalent functions- A
BadgeCreation
API based on AnyBadge.NET enables creation of badges that visualize the validation results. - export of the validation results as a
junit
xml file enables further integration into e.g. CI/CD pipelines
User-facing APIs:
-
Validate
:- validate ControlledVocabulary tokens, e.g. for their compliance with a reference ontology or for the type and shape of annotated value
-
BadgeCreation
:- Create and style small .svg images that visualize the validation results of a validation suite
Execute
- perform actions (e.g. running validation, writing files result to disk)
Additional APIs:
-
OBOGraph
- Create, complete, and query the graph representation of an ontology
-
ARCGraph
- Create, complete, and query a graph of ControlledVocabulary tokens based on the relations in a reference ontology
Creating a validation case
ARCExpect offers a validationCase
Computation expression that enables the creation of validation cases in a very concise and readable way.
Suppose you have a metadata token that annotates the value 42 with the term "Thing" from the "Some Ontology" ontology (meaning this token represents "42 Things").
open ControlledVocabulary
let testParam =
CvParam(
CvTerm.create("SO:000001","Thing","Some Ontology"),
ParamValue.Value 42
)
Use the validationCase
CE to creater a validation case, and use the Validate
API to specify the validation step:
let myValidationCase =
validationCase (TestID.Name "has value 42") {
testParam |> Validate.Param.ValueIsEqualTo 42
}
this will create a validation case that checks if the value of the given token is 42.
Let's take a closer look at some API specifics: The Validate
API is designed to be very close to natural language.
Validate.Param.ValueIsEqualTo 42
means:
"validate (for a) Param (that its) value is equal to 42".
Where Param
is any type that implements the IParam
interface from ControlledVocabulary
- an interface that can be used to represent a value annotated with some controlled vocabulary.
Performing validation
Use the Execute
API to perform the validation, obtaining a summary object
let validationResults = Execute.Validation(myValidationCase)
validationResults.results
|> List.head
|> snd
{ result = Passed\n count = 1\n meanDuration = 0.0\n maxDuration = 0.0 }
result Passed
tag Passed
order 1
isPassed Passed
isIgnored Passed
isFailed Passed
isException False
count 1
meanDuration 0
maxDuration 0
duration 00:00:00
Creating validation badges
Use the BadgeCreation
API to create badges that visualize the validation results.
let myBadge =
validationResults
|> BadgeCreation.ofTestResults(
labelText = "My validation"
)
You can also use Execute.BadgeCreation
to write directly to a file:
validationResults
|> Execute.BadgeCreation(
path = "some/path/here.svg",
labelText = "My validation"
)
Exporting JUnit XML
Use the Execute.JUnitSummaryCreation
API to export the validation results as a junit
xml file.
validationResults
|> Execute.JUnitSummaryCreation(
path = "some/path/here.xml"
)
Performing a ValidationPipeline
use the Execute.ValidationPipeline
API to perform a validation pipeline consisting of these steps:
- run the validation cases and collect the results
- create the badge at the given path
- export the junit summary at the given path
myValidationCase
|> Execute.ValidationPipeline(
jUnitPath = "some/path/here.xml",
badgePath = "some/path/here.svg",
labelText = "My validation"
)
type CvParam = inherit CvAttributeCollection interface IParam new: cvAccession: string * cvName: string * cvRef: string * paramValue: ParamValue * attributes: IDictionary<string,IParam> -> CvParam + 6 overloads member Equals: term: CvTerm -> bool + 2 overloads override ToString: unit -> string member WithValue: v: ParamValue -> CvParam static member equals: cvp1: CvParam -> cvp2: CvParam -> bool static member equalsName: cvp1: CvParam -> cvp2: CvParam -> bool static member equalsTerm: term: CvTerm -> cvp: CvParam -> bool static member fromCategory: category: CvTerm -> term: CvTerm -> CvParam ...
<summary> Represents a structured value, annotated with a controlled vocabulary term Attributes can be used to further describe the CvParam </summary>
--------------------
new: cvTerm: CvTerm * pv: ParamValue -> CvParam
new: cvTerm: CvTerm * v: System.IConvertible -> CvParam
new: term: CvTerm * pv: ParamValue * attributes: IParam seq -> CvParam
new: id: string * name: string * ref: string * pv: ParamValue -> CvParam
new: id: string * name: string * ref: string * v: System.IConvertible -> CvParam
new: cvAccession: string * cvName: string * cvRef: string * paramValue: ParamValue * attributes: System.Collections.Generic.IDictionary<string,IParam> -> CvParam
new: id: string * name: string * ref: string * pv: ParamValue * attributes: IParam seq -> CvParam
<summary> Represents a term from a controlled vocabulary (Cv) in the form of: id|accession ; name|value ; refUri </summary>
static member CvTerm.create: accession: string * name: string * ref: string -> CvTerm
<summary> Represent the different cases of a parameter, which is either a simple value, a CvTerm or a simple value with CvUnit </summary>
module List from Microsoft.FSharp.Collections
--------------------
type List<'T> = | op_Nil | op_ColonColon of Head: 'T * Tail: 'T list interface IReadOnlyList<'T> interface IReadOnlyCollection<'T> interface IEnumerable interface IEnumerable<'T> member GetReverseIndex: rank: int * offset: int -> int member GetSlice: startIndex: int option * endIndex: int option -> 'T list static member Cons: head: 'T * tail: 'T list -> 'T list member Head: 'T member IsEmpty: bool member Item: index: int -> 'T with get ...