Skip to content

Commit

Permalink
Add ValidationSummary
Browse files Browse the repository at this point in the history
- Includes initial specs laid out in #95
- Add F#-friendly serialization via FSharp.System.Text.Json
- Add tests
  • Loading branch information
kMutagene committed Apr 24, 2024
1 parent 4d70e78 commit e022116
Show file tree
Hide file tree
Showing 6 changed files with 367 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/ARCExpect/ARCExpect.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<Compile Include="ARCGraph.fs" />
<Compile Include="ARCExpect.fs" />
<Compile Include="ValidationFunctions.fs" />
<Compile Include="ValidationSummary.fs" />
<Compile Include="TopLevelAPI.fs" />
<Compile Include="Configs\PathConfig.fs" />
<Compile Include="Configs\ARCConfig.fs" />
Expand All @@ -36,5 +37,6 @@
<PackageReference Include="OBO.NET" Version="[0.4.2]" />
<PackageReference Include="Cytoscape.NET" Version="[0.2.0]" />
<PackageReference Include="AnyBadge.NET" Version="[2.0.0]" />
<PackageReference Include="FSharp.SystemTextJson" Version="[1.3.13]" />
</ItemGroup>
</Project>
9 changes: 9 additions & 0 deletions src/ARCExpect/InternalUtils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

open System
open Graphoscope
open System.Text.Json
open System.Text.Json.Serialization


//// this is needed to allow ValidatorTests project to access internal modules
Expand All @@ -20,6 +22,13 @@ module InternalUtils =
open OBO.NET
open ControlledVocabulary

/// internal json options for better F# type support in serialization (mainly for Options)
module JsonOptions =
let options =
JsonFSharpOptions.Default()
.WithSkippableOptionFields() // if option is none, do not include a property, but include it if option is some.
.ToJsonSerializerOptions()


module String =

Expand Down
104 changes: 104 additions & 0 deletions src/ARCExpect/ValidationSummary.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
namespace ARCExpect

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

/// <summary>
/// Represents a brief summary of the result of validating an ARC against a set of validation cases.
/// </summary>
type ValidationResult = {
HasFailures: bool
Total: int
Passed: int
Failed: int
Errored: int
} with
static member create(
hasFailures: bool,
total: int,
passed: int,
failed: int,
errored: int
) = {
HasFailures = hasFailures
Total = total
Passed = passed
Failed = failed
Errored = errored
}

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

static member ofTestRunSummary (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
)

/// <summary>
/// Represents a brief summary of a validation package. Should be expanded to include full package metadata in the future.
/// </summary>
type ValidationPackageSummary = {
Name: string
Version: string
HookEndpoint: string option
} with
static member create(
name: string,
version: string,
?HookEndpoint: string
) = {
Name = name
Version = version
HookEndpoint = HookEndpoint
}

/// <summary>
/// Represents a summary of the validation results of an ARC against a validation package containing critical and non-critical validation cases.
/// </summary>
type ValidationSummary = {
Critical: ValidationResult
NonCritical: ValidationResult
ValidationPackage: ValidationPackageSummary
} with
static member create(
critical: ValidationResult,
nonCritical: ValidationResult,
validationPackage: ValidationPackageSummary
) = {
Critical = critical
NonCritical = nonCritical
ValidationPackage = validationPackage
}
static member ofTestRunSummaries (
criticalSummary: Impl.TestRunSummary,
nonCriticalSummary: Impl.TestRunSummary,
package: ValidationPackageSummary
) =
ValidationSummary.create(
critical = ValidationResult.ofTestRunSummary criticalSummary,
nonCritical = ValidationResult.ofTestRunSummary nonCriticalSummary,
validationPackage = package
)

static member toJson (summary: ValidationSummary) =
JsonSerializer.Serialize(summary, JsonOptions.options)

static member fromJson (json: string) =
JsonSerializer.Deserialize<ValidationSummary>(json, JsonOptions.options)

static member writeJson (path: string) (summary: ValidationSummary) =
File.WriteAllText(path, ValidationSummary.toJson summary)
7 changes: 5 additions & 2 deletions tests/ARCExpect.Tests/ARCExpect.Tests.fsproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>

<ItemGroup>
<None Include="fixtures\**" CopyToOutputDirectory="Always" />
<EmbeddedResource Remove="CLITests\**" />
Expand All @@ -17,9 +19,10 @@
<Compile Include="ParamCollectionTests.fs" />
<Compile Include="ARCExpectTests.fs" />
<Compile Include="ARCGraphTests.fs" />
<Compile Include="ARCSpecification.fs" />
<Compile Include="ValidationSummaryTests.fs" />
<Compile Include="Main.fs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Expecto" Version="9.*" />
<PackageReference Include="YoloDev.Expecto.TestSdk" Version="0.*" />
Expand All @@ -28,4 +31,4 @@
<ProjectReference Include="..\..\src\ARCExpect\ARCExpect.fsproj" />
<ProjectReference Include="..\Common\Common.fsproj" />
</ItemGroup>
</Project>
</Project>
97 changes: 96 additions & 1 deletion tests/ARCExpect.Tests/ReferenceObjects.fs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module ReferenceObjects

open ControlledVocabulary
open ARCExpect

module CvTerms =

Expand All @@ -16,4 +17,98 @@ module CvParams =

let ``Investigation Person Email (valid)`` = CvParam(CvTerms.``Investigation Person Email``, ParamValue.Value "[email protected]")

let ``Investigation Person Email (invalid)`` = CvParam(CvTerms.``Investigation Person Email``, ParamValue.Value "nope")
let ``Investigation Person Email (invalid)`` = CvParam(CvTerms.``Investigation Person Email``, ParamValue.Value "nope")

module ValidationResult =

let allPassed = {
HasFailures = false
Total = 1
Passed = 1
Failed = 0
Errored = 0
}

let allFailed = {
HasFailures = true
Total = 1
Passed = 0
Failed = 1
Errored = 0
}

module ValidationPackageSummary =

let noHook = {
Name = "test"
Version = "1.0.0"
HookEndpoint = None
}

let withHook = {
Name = "test"
Version = "1.0.0"
HookEndpoint = Some "http://test.com"
}

module ValidationSummary =

let allPassedNoHook =
{
Critical = ValidationResult.allPassed
NonCritical = ValidationResult.allPassed
ValidationPackage = ValidationPackageSummary.noHook
}

let allPassedNoHookJson = """{"Critical":{"HasFailures":false,"Total":1,"Passed":1,"Failed":0,"Errored":0},"NonCritical":{"HasFailures":false,"Total":1,"Passed":1,"Failed":0,"Errored":0},"ValidationPackage":{"Name":"test","Version":"1.0.0"}}"""

let allPassedWithHook =
{
Critical = ValidationResult.allPassed
NonCritical = ValidationResult.allPassed
ValidationPackage = ValidationPackageSummary.withHook
}

let allPassedWithHookJson = """{"Critical":{"HasFailures":false,"Total":1,"Passed":1,"Failed":0,"Errored":0},"NonCritical":{"HasFailures":false,"Total":1,"Passed":1,"Failed":0,"Errored":0},"ValidationPackage":{"Name":"test","Version":"1.0.0","HookEndpoint":"http://test.com"}}"""

let allFailedNoHook =
{
Critical = ValidationResult.allFailed
NonCritical = ValidationResult.allFailed
ValidationPackage = ValidationPackageSummary.noHook
}

let allFailedWithHook =
{
Critical = ValidationResult.allFailed
NonCritical = ValidationResult.allFailed
ValidationPackage = ValidationPackageSummary.withHook
}

let nonCriticalFailedNoHook =
{
Critical = ValidationResult.allPassed
NonCritical = ValidationResult.allFailed
ValidationPackage = ValidationPackageSummary.noHook
}

let nonCriticalFailedWithHook =
{
Critical = ValidationResult.allPassed
NonCritical = ValidationResult.allFailed
ValidationPackage = ValidationPackageSummary.withHook
}

let criticalFailedNoHook =
{
Critical = ValidationResult.allFailed
NonCritical = ValidationResult.allPassed
ValidationPackage = ValidationPackageSummary.noHook
}

let criticalFailedWithHook =
{
Critical = ValidationResult.allFailed
NonCritical = ValidationResult.allPassed
ValidationPackage = ValidationPackageSummary.withHook
}
Loading

0 comments on commit e022116

Please sign in to comment.