Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ValidationSummary and rework ARCExpect top level API #99

Merged
merged 7 commits into from
Apr 29, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Re-order some modules and expand summary type to include original run…
… summary:

- add a way to get specification validation cases for supported specs
- reflect changes in tests and tool
kMutagene committed Apr 26, 2024
commit 2b409336a5b4fce404fff39c0d16279aa06088c0
7 changes: 5 additions & 2 deletions src/ARCExpect/ARCExpect.fsproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
@@ -18,9 +18,11 @@
<Compile Include="ARCGraph.fs" />
<Compile Include="ARCExpect.fs" />
<Compile Include="ValidationFunctions.fs" />
<Compile Include="ARCValidationPackage.fs" />
<Compile Include="ValidationSummary.fs" />
<Compile Include="SpecificationValidation\V2_0_0_Draft.fs" />
<Compile Include="SpecificationValidation\SpecificationSelection.fs" />
<Compile Include="TopLevelAPI.fs" />
<Compile Include="ARCSpecification.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Expecto" Version="[9.0.4]" />
@@ -33,5 +35,6 @@
<PackageReference Include="Cytoscape.NET" Version="[0.2.0]" />
<PackageReference Include="AnyBadge.NET" Version="[2.0.0]" />
<PackageReference Include="FSharp.SystemTextJson" Version="[1.3.13]" />
<PackageReference Include="AVPRIndex" Version="[0.1.0]" />
</ItemGroup>
</Project>
20 changes: 20 additions & 0 deletions src/ARCExpect/SpecificationValidation/SpecificationSelection.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace ARCExpect.SpecificationValidation

module SpecificationSelection =

open ARCExpect

let [<Literal>] latest = "2.0.0-draft"

let internal specMap =
[
"2.0.0-draft" , SpecificationValidation.V2_0_0_Draft.validationCases
] |> Map.ofSeq

let tryGetValidationCasesForSpecificationVersion (specVersion: string) (path: string) =

let specVersion = if specVersion = "latest" then latest else specVersion

match specMap.TryFind specVersion with
| Some generator -> specVersion, generator path
| None -> failwithf "No validation cases found for specification version '%s'" specVersion
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
namespace ARCExpect.ARCSpecification
namespace ARCExpect.SpecificationValidation

open ControlledVocabulary
open ARCTokenization
open ARCExpect
open Expecto

module V2_Draft =
module V2_0_0_Draft =

module MustHaveTerms =
let investigationTerms =
7 changes: 4 additions & 3 deletions src/ARCExpect/TopLevelAPI.fs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace ARCExpect


namespace ARCExpect
open AnyBadge.NET
open Expecto
open System.IO
@@ -78,4 +78,5 @@ type Execute =
let labelText = defaultArg BadgeLabelText packageName

results
|> Execute.BadgeCreation(badgePath, labelText, ?ValueSuffix = ValueSuffix, ?Thresholds = Thresholds, ?DefaultColor = DefaultColor)
|> Execute.BadgeCreation(badgePath, labelText, ?ValueSuffix = ValueSuffix, ?Thresholds = Thresholds, ?DefaultColor = DefaultColor)

23 changes: 15 additions & 8 deletions src/ARCExpect/ValidationSummary.fs
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

open Expecto
open System.Text.Json
open System.Text.Json.Serialization
open System.IO

/// <summary>
@@ -13,39 +14,45 @@ type ValidationResult = {
Passed: int
Failed: int
Errored: int
[<JsonIgnore>]
OriginalRunSummary: Impl.TestRunSummary option
} with
static member create(
hasFailures: bool,
total: int,
passed: int,
failed: int,
errored: int
errored: int,
?OriginalRunSummary: Impl.TestRunSummary
) = {
HasFailures = hasFailures
Total = total
Passed = passed
Failed = failed
Errored = errored
OriginalRunSummary = OriginalRunSummary
}

static member create (total: int, passed: int, failed: int, errored: int) =
static member create (total: int, passed: int, failed: int, errored: int, ?OriginalRunSummary: Impl.TestRunSummary) =
ValidationResult.create(
hasFailures = (failed > 0 || errored > 0),
total = total,
passed = passed,
failed = failed,
errored = errored
errored = errored,
?OriginalRunSummary = OriginalRunSummary
)

static member ofTestRunSummary (summary: Impl.TestRunSummary) =
static member ofExpectoTestRunSummary (summary: Impl.TestRunSummary) =

let totalTests = summary.errored @ summary.failed @ summary.ignored @ summary.passed

ValidationResult.create(
total = totalTests.Length,
passed = summary.passed.Length,
errored = summary.errored.Length,
failed = summary.failed.Length
failed = summary.failed.Length,
OriginalRunSummary = summary
)

/// <summary>
@@ -83,14 +90,14 @@ type ValidationSummary = {
NonCritical = nonCritical
ValidationPackage = validationPackage
}
static member ofTestRunSummaries (
static member ofExpectoTestRunSummaries (
criticalSummary: Impl.TestRunSummary,
nonCriticalSummary: Impl.TestRunSummary,
package: ValidationPackageSummary
) =
ValidationSummary.create(
critical = ValidationResult.ofTestRunSummary criticalSummary,
nonCritical = ValidationResult.ofTestRunSummary nonCriticalSummary,
critical = ValidationResult.ofExpectoTestRunSummary criticalSummary,
nonCritical = ValidationResult.ofExpectoTestRunSummary nonCriticalSummary,
validationPackage = package
)

16 changes: 10 additions & 6 deletions src/arc-validate/APIs/ValidateAPI.fs
Original file line number Diff line number Diff line change
@@ -50,27 +50,31 @@ module ValidateAPI =
]
|> List.iter AnsiConsole.MarkupLine

let specVersion = defaultArg (args.TryGetResult(Specification_Version)) "latest"
let status = AnsiConsole.Status()
let mutable exitCode = ExitCode.Success

status.Start($"Performing validation against the ARC specification V2_Draft", fun ctx ->
status.Start($"Performing validation against version '{specVersion}' of the ARC specification", fun ctx ->

let version_used, validationCases = SpecificationValidation.SpecificationSelection.tryGetValidationCasesForSpecificationVersion specVersion root

if specVersion = "latest" then printfn $"latest spec version supported is {version_used}"

if verbose then

AnsiConsole.MarkupLine("LOG: Running in:")
AnsiConsole.Write(TextPath(Path.GetFullPath(root)))
AnsiConsole.MarkupLine("")
AnsiConsole.MarkupLine($"LOG: running validation against [bold underline green]ARC specification V2_Draft[/].")
AnsiConsole.MarkupLine($"LOG: running validation against [bold underline green] version '{specVersion}' of the ARC specification[/].")
AnsiConsole.MarkupLine($"LOG: Output path is:")
AnsiConsole.Write(TextPath(Path.GetFullPath(outPath)))
AnsiConsole.MarkupLine("")

let cases = ARCSpecification.V2_Draft.validationCases root


let outDirBadge = System.IO.Path.Combine(root, "ARC_specification_V2_Draft.svg")
let outDirResXml =System.IO.Path.Combine(root, "ARC_specification_V2_Draft.xml")
let outDirResXml = System.IO.Path.Combine(root, "ARC_specification_V2_Draft.xml")

let results = ARCExpect.Execute.Validation cases
let results = ARCExpect.Execute.Validation validationCases

results
|> Execute.JUnitSummaryCreation(outDirResXml)
2 changes: 2 additions & 0 deletions src/arc-validate/CLIArgs/ValidateArgs.fs
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ type ValidateArgs =
| [<Unique; AltCommandLine("-o")>] Out_Directory of path:string
| [<Unique; AltCommandLine("-p")>] Package of package_name:string
| [<Unique; AltCommandLine("-v")>] Package_Version of package_version:string
| [<Unique>] Specification_Version of specification_version: string
| [<Unique>] Preview

interface IArgParserTemplate with
@@ -15,4 +16,5 @@ type ValidateArgs =
| ARC_Directory _ -> "Optional. Specify a directory that contains the arc to convert. Default: content of the ARC_PATH environment variable. If ARC_PATH is not set: current directory."
| Package _ -> "Optional. Specify a validation package to use on top of the default validation for invenio export. Default: no package is used, only structural validation for invenio export."
| Package_Version _ -> "Optional. Specify a version of the validation package to use. If no version is specified, the latest version will be used."
| Specification_Version _ -> "Optional. Only has an effect if no package is specified via '-p' Specify a version of the ARC specification to validate against. Default: 'latest'."
| Preview -> "Optional. Use the preview version of the package."
1 change: 1 addition & 0 deletions tests/ARCExpect.Tests/ARCExpect.Tests.fsproj
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
<ItemGroup>
<None Include="fixtures\**" CopyToOutputDirectory="Always" />
<EmbeddedResource Remove="CLITests\**" />
<Compile Include="TestUtils.fs" />
<Compile Include="InternalUtilsTests.fs" />
<Compile Include="StringValidationPatternTests.fs" />
<Compile Include="ReferenceObjects.fs" />
2 changes: 2 additions & 0 deletions tests/ARCExpect.Tests/ReferenceObjects.fs
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ module ValidationResult =
Passed = 1
Failed = 0
Errored = 0
OriginalRunSummary = None
}

let allFailed = {
@@ -35,6 +36,7 @@ module ValidationResult =
Passed = 0
Failed = 1
Errored = 0
OriginalRunSummary = None
}

module ValidationPackageSummary =
24 changes: 24 additions & 0 deletions tests/ARCExpect.Tests/TestUtils.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module TestUtils

open Expecto
open ARCExpect

module Expect =

let validationResultEqualIgnoringOriginal (actual: ARCExpect.ValidationResult) (expected: ARCExpect.ValidationResult) =
let actual = { actual with OriginalRunSummary = None }
let expected = { expected with OriginalRunSummary = None }
Expect.isTrue (actual = expected) "validation results were not equal ignoring the original run summaries."

let validationSummaryEqualIgnoringOriginal (actual: ARCExpect.ValidationSummary) (expected: ARCExpect.ValidationSummary) =
let actual = {
actual with
Critical.OriginalRunSummary = None
NonCritical.OriginalRunSummary = None
}
let expected = {
expected with
Critical.OriginalRunSummary = None
NonCritical.OriginalRunSummary = None
}
Expect.isTrue (actual = expected) "validation summaries were not equal ignoring the original run summaries."
55 changes: 35 additions & 20 deletions tests/ARCExpect.Tests/ValidationSummaryTests.fs
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

open ARCExpect
open Expecto
open TestUtils

let dummyTestPassed = testCase "dummyTest1" (fun _ -> Expect.isTrue true "is not true") |> performTest
let dummyTestFailed = testCase "dummyTest2" (fun _ -> Expect.isTrue false "is not true") |> performTest
@@ -26,12 +27,12 @@ let ``ValidationResult tests`` =
testList "ValidationSummary tests" [
testList "ValidationResult" [
test "correct result is created from passed TestRunSummary" {
let actual = ValidationResult.ofTestRunSummary dummyTestPassed
Expect.equal actual ReferenceObjects.ValidationResult.allPassed "validation result was not equal"
let actual = ValidationResult.ofExpectoTestRunSummary dummyTestPassed
Expect.validationResultEqualIgnoringOriginal actual ReferenceObjects.ValidationResult.allPassed
}
test "correct result is created from failed TestRunSummary" {
let actual = ValidationResult.ofTestRunSummary dummyTestFailed
Expect.equal actual ReferenceObjects.ValidationResult.allFailed "validation result was not equal"
let actual = ValidationResult.ofExpectoTestRunSummary dummyTestFailed
Expect.validationResultEqualIgnoringOriginal actual ReferenceObjects.ValidationResult.allFailed
}
]
testList "ValidationPackageSummary" [
@@ -53,69 +54,69 @@ let ``ValidationResult tests`` =
]
testList "ValidationSummary" [
test "critial passed, noncritical passed, package with no hook is created correctly from TestRunSummaries" {
let actual = ValidationSummary.ofTestRunSummaries(
let actual = ValidationSummary.ofExpectoTestRunSummaries(
criticalSummary = dummyTestPassed,
nonCriticalSummary = dummyTestPassed,
package = testPackageNoHook
)
Expect.equal actual ReferenceObjects.ValidationSummary.allPassedNoHook "validation summary was not equal"
Expect.validationSummaryEqualIgnoringOriginal actual ReferenceObjects.ValidationSummary.allPassedNoHook
}
test "critial passed, noncritical passed, package with hook is created correctly from TestRunSummaries" {
let actual = ValidationSummary.ofTestRunSummaries(
let actual = ValidationSummary.ofExpectoTestRunSummaries(
criticalSummary = dummyTestPassed,
nonCriticalSummary = dummyTestPassed,
package = testPackageWithHook
)
Expect.equal actual ReferenceObjects.ValidationSummary.allPassedWithHook "validation summary was not equal"
Expect.validationSummaryEqualIgnoringOriginal actual ReferenceObjects.ValidationSummary.allPassedWithHook
}
test "critial passed, noncritical failed, package with no hook is created correctly from TestRunSummaries" {
let actual = ValidationSummary.ofTestRunSummaries(
let actual = ValidationSummary.ofExpectoTestRunSummaries(
criticalSummary = dummyTestPassed,
nonCriticalSummary = dummyTestFailed,
package = testPackageNoHook
)
Expect.equal actual ReferenceObjects.ValidationSummary.nonCriticalFailedNoHook "validation summary was not equal"
Expect.validationSummaryEqualIgnoringOriginal actual ReferenceObjects.ValidationSummary.nonCriticalFailedNoHook
}
test "critial passed, noncritical failed, package with hook is created correctly from TestRunSummaries" {
let actual = ValidationSummary.ofTestRunSummaries(
let actual = ValidationSummary.ofExpectoTestRunSummaries(
criticalSummary = dummyTestPassed,
nonCriticalSummary = dummyTestFailed,
package = testPackageWithHook
)
Expect.equal actual ReferenceObjects.ValidationSummary.nonCriticalFailedWithHook "validation summary was not equal"
Expect.validationSummaryEqualIgnoringOriginal actual ReferenceObjects.ValidationSummary.nonCriticalFailedWithHook
}

test "critial failed, noncritical passed, package with no hook is created correctly from TestRunSummaries" {
let actual = ValidationSummary.ofTestRunSummaries(
let actual = ValidationSummary.ofExpectoTestRunSummaries(
criticalSummary = dummyTestFailed,
nonCriticalSummary = dummyTestPassed,
package = testPackageNoHook
)
Expect.equal actual ReferenceObjects.ValidationSummary.criticalFailedNoHook "validation summary was not equal"
Expect.validationSummaryEqualIgnoringOriginal actual ReferenceObjects.ValidationSummary.criticalFailedNoHook
}
test "critial failed, noncritical passed, package with hook is created correctly from TestRunSummaries" {
let actual = ValidationSummary.ofTestRunSummaries(
let actual = ValidationSummary.ofExpectoTestRunSummaries(
criticalSummary = dummyTestFailed,
nonCriticalSummary = dummyTestPassed,
package = testPackageWithHook
)
Expect.equal actual ReferenceObjects.ValidationSummary.criticalFailedWithHook "validation summary was not equal"
Expect.validationSummaryEqualIgnoringOriginal actual ReferenceObjects.ValidationSummary.criticalFailedWithHook
}
test "critial failed, noncritical failed, package with no hook is created correctly from TestRunSummaries" {
let actual = ValidationSummary.ofTestRunSummaries(
let actual = ValidationSummary.ofExpectoTestRunSummaries(
criticalSummary = dummyTestFailed,
nonCriticalSummary = dummyTestFailed,
package = testPackageNoHook
)
Expect.equal actual ReferenceObjects.ValidationSummary.allFailedNoHook "validation summary was not equal"
Expect.validationSummaryEqualIgnoringOriginal actual ReferenceObjects.ValidationSummary.allFailedNoHook
}
test "critial failed, noncritical failed, package with hook is created correctly from TestRunSummaries" {
let actual = ValidationSummary.ofTestRunSummaries(
let actual = ValidationSummary.ofExpectoTestRunSummaries(
criticalSummary = dummyTestFailed,
nonCriticalSummary = dummyTestFailed,
package = testPackageWithHook
)
Expect.equal actual ReferenceObjects.ValidationSummary.allFailedWithHook "validation summary was not equal"
Expect.validationSummaryEqualIgnoringOriginal actual ReferenceObjects.ValidationSummary.allFailedWithHook
}
]
testList "Serialization" [
@@ -147,5 +148,19 @@ let ``ValidationResult tests`` =

Expect.equal actual ReferenceObjects.ValidationSummary.allPassedWithHook "roundtrip was not equal"
}
test "roundtrip looses original summary" {

let initial = ValidationSummary.ofExpectoTestRunSummaries(dummyTestPassed, dummyTestPassed, ReferenceObjects.ValidationPackageSummary.noHook)
let actual =
ValidationSummary.ofExpectoTestRunSummaries(dummyTestPassed, dummyTestPassed, ReferenceObjects.ValidationPackageSummary.noHook)
|> ValidationSummary.toJson
|> ValidationSummary.fromJson

Expect.isSome initial.Critical.OriginalRunSummary "OriginalRunSummary was not some initially"
Expect.isNone actual.Critical.OriginalRunSummary "OriginalRunSummary was not none after json roundtrip"
Expect.isSome initial.NonCritical.OriginalRunSummary "OriginalRunSummary was not some initially"
Expect.isNone actual.NonCritical.OriginalRunSummary "OriginalRunSummary was not none after json roundtrip"

}
]
]