mirror of
https://github.com/Smaug123/unofficial-nunit-runner
synced 2025-10-06 01:48:38 +00:00
Compare commits
94 Commits
WoofWare.N
...
WoofWare.N
Author | SHA1 | Date | |
---|---|---|---|
|
226da02b1b | ||
|
e9b9366b90 | ||
|
e7c31b5366 | ||
|
9d26610384 | ||
|
61fbb5f55b | ||
|
d9938d96a3 | ||
|
874a367ce3 | ||
|
4300fbe6b8 | ||
|
402b98f85c | ||
|
a795d6222c | ||
|
cf482b677b | ||
|
db27a7acc8 | ||
|
99826df864 | ||
|
1c93b2c4b2 | ||
|
4369b35dd1 | ||
|
a183455f55 | ||
|
de5f5a64ef | ||
|
fdddbf828b | ||
|
67d9d71100 | ||
|
c39745280b | ||
|
26c29d63bc | ||
|
78f7f76074 | ||
|
c2401207c4 | ||
|
46e097a02e | ||
|
7c23c3bb1c | ||
|
ace1417de6 | ||
|
a694637958 | ||
|
8626cc1252 | ||
|
0287a6b7eb | ||
|
8579ee8f8b | ||
|
debda1a557 | ||
|
bf7d846f61 | ||
|
4690bf23ad | ||
|
04283ee961 | ||
|
6c61c2cbf1 | ||
|
2a0cabd3a9 | ||
|
111e019a83 | ||
|
16d353e8df | ||
|
8528da77aa | ||
|
b74ae980d7 | ||
|
318ba70608 | ||
|
1ee38136a1 | ||
|
3d8bb8d0ca | ||
|
2f64191348 | ||
|
86b8c0ec64 | ||
|
e088d2b420 | ||
|
3ea9d94861 | ||
|
e003ef0934 | ||
|
50948e629c | ||
|
b14e5ede40 | ||
|
f256eb7b29 | ||
|
ec7d9187c5 | ||
|
62eb3c5a66 | ||
|
97e7a87e6a | ||
|
14d91840b2 | ||
|
2859a5f6e6 | ||
|
64649b76ce | ||
|
c9f013891b | ||
|
a7660d1c38 | ||
|
d49d36206e | ||
|
881d5227e7 | ||
|
6564835ee4 | ||
|
db2ecdfa43 | ||
|
5b376cc592 | ||
|
4d34382cd3 | ||
|
c26e4f085d | ||
|
b002be5d72 | ||
|
5483184edc | ||
|
3596b8a3a8 | ||
|
68326d7628 | ||
|
f4b0a5457b | ||
|
c4b67304a1 | ||
|
337a0635d2 | ||
|
e8e302db2d | ||
|
1522e3cc9c | ||
|
81c6b584a4 | ||
|
40824e06e7 | ||
|
fb945c04ac | ||
|
85cd116d52 | ||
|
8e7c54cc83 | ||
|
378a0169f8 | ||
|
870804d6ef | ||
|
9f5f22c644 | ||
|
296f230616 | ||
|
56ac203570 | ||
|
e17e769d5a | ||
|
57c34e0c4c | ||
|
7f9464b826 | ||
|
3d04199c56 | ||
|
9d4b893e02 | ||
|
55e9645316 | ||
|
e9dc768449 | ||
|
e0b2d52812 | ||
|
2ed4a04f70 |
@@ -3,13 +3,13 @@
|
|||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"fantomas": {
|
"fantomas": {
|
||||||
"version": "6.3.9",
|
"version": "6.3.16",
|
||||||
"commands": [
|
"commands": [
|
||||||
"fantomas"
|
"fantomas"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"fsharp-analyzers": {
|
"fsharp-analyzers": {
|
||||||
"version": "0.26.0",
|
"version": "0.28.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"fsharp-analyzers"
|
"fsharp-analyzers"
|
||||||
]
|
]
|
||||||
|
@@ -1,40 +1,40 @@
|
|||||||
root=true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
charset=utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace=true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline=true
|
insert_final_newline = true
|
||||||
indent_style=space
|
indent_style = space
|
||||||
indent_size=4
|
indent_size = 4
|
||||||
|
|
||||||
# ReSharper properties
|
# ReSharper properties
|
||||||
resharper_xml_indent_size=2
|
resharper_xml_indent_size = 2
|
||||||
resharper_xml_max_line_length=100
|
resharper_xml_max_line_length = 100
|
||||||
resharper_xml_tab_width=2
|
resharper_xml_tab_width = 2
|
||||||
|
|
||||||
[*.{csproj,fsproj,sqlproj,targets,props,ts,tsx,css,json}]
|
[*.{csproj,fsproj,sqlproj,targets,props,ts,tsx,css,json}]
|
||||||
indent_style=space
|
indent_style = space
|
||||||
indent_size=2
|
indent_size = 2
|
||||||
|
|
||||||
[*.{fs,fsi}]
|
[*.{fs,fsi}]
|
||||||
fsharp_bar_before_discriminated_union_declaration=true
|
fsharp_bar_before_discriminated_union_declaration = true
|
||||||
fsharp_space_before_uppercase_invocation=true
|
fsharp_space_before_uppercase_invocation = true
|
||||||
fsharp_space_before_class_constructor=true
|
fsharp_space_before_class_constructor = true
|
||||||
fsharp_space_before_member=true
|
fsharp_space_before_member = true
|
||||||
fsharp_space_before_colon=true
|
fsharp_space_before_colon = true
|
||||||
fsharp_space_before_semicolon=true
|
fsharp_space_before_semicolon = true
|
||||||
fsharp_multiline_bracket_style=aligned
|
fsharp_multiline_bracket_style = aligned
|
||||||
fsharp_newline_between_type_definition_and_members=true
|
fsharp_newline_between_type_definition_and_members = true
|
||||||
fsharp_align_function_signature_to_indentation=true
|
fsharp_align_function_signature_to_indentation = true
|
||||||
fsharp_alternative_long_member_definitions=true
|
fsharp_alternative_long_member_definitions = true
|
||||||
fsharp_multi_line_lambda_closing_newline=true
|
fsharp_multi_line_lambda_closing_newline = true
|
||||||
fsharp_experimental_keep_indent_in_branch=true
|
fsharp_experimental_keep_indent_in_branch = true
|
||||||
fsharp_max_value_binding_width=80
|
fsharp_max_value_binding_width = 80
|
||||||
fsharp_max_record_width=0
|
fsharp_max_record_width = 0
|
||||||
max_line_length=120
|
max_line_length = 120
|
||||||
end_of_line=lf
|
end_of_line = lf
|
||||||
|
|
||||||
[*.{appxmanifest,build,dtd,nuspec,xaml,xamlx,xoml,xsd}]
|
[*.{appxmanifest,build,dtd,nuspec,xaml,xamlx,xoml,xsd}]
|
||||||
indent_style=space
|
indent_style = space
|
||||||
indent_size=2
|
indent_size = 2
|
||||||
tab_width=2
|
tab_width = 2
|
||||||
|
1
.fantomasignore
Normal file
1
.fantomasignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.direnv/
|
221
.github/workflows/dotnet.yaml
vendored
221
.github/workflows/dotnet.yaml
vendored
@@ -29,7 +29,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@V27
|
uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -38,7 +38,30 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: 'nix develop --command dotnet build --no-restore --configuration ${{matrix.config}}'
|
run: 'nix develop --command dotnet build --no-restore --configuration ${{matrix.config}}'
|
||||||
- name: Test
|
- name: Test
|
||||||
run: 'nix develop --command dotnet test --no-build --verbosity normal --configuration ${{matrix.config}}'
|
run: |
|
||||||
|
nix develop --command dotnet test --no-build --verbosity normal --configuration ${{matrix.config}} --framework net8.0 --filter 'FullyQualifiedName !~ FailingConsumer'
|
||||||
|
|
||||||
|
selftest-intended-failures:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||||
|
- name: Install Nix
|
||||||
|
uses: cachix/install-nix-action@v30
|
||||||
|
with:
|
||||||
|
extra_nix_config: |
|
||||||
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Restore dependencies
|
||||||
|
run: nix develop --command dotnet restore
|
||||||
|
- name: Build
|
||||||
|
run: 'nix develop --command dotnet build --no-restore --configuration Release'
|
||||||
|
- name: Test using self
|
||||||
|
run: 'nix develop --command dotnet exec ./WoofWare.NUnitTestRunner/bin/Release/net6.0/WoofWare.NUnitTestRunner.dll ./FailingConsumer/bin/Release/net8.0/FailingConsumer.dll --trx TrxOut/out.trx || true'
|
||||||
|
- name: Munge output
|
||||||
|
run: 'nix develop --command xmlstarlet sel -N x="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" -t -m "//x:UnitTestResult" -v "@testName" -o ": " -v ".//x:ErrorInfo/x:Message" -n TrxOut/out.trx > snapshot.txt'
|
||||||
|
- name: Check output matches expected
|
||||||
|
run: 'actual=$(cat snapshot.txt | sort) expected=$(cat FailingConsumer/expected.txt | sort) [ "$expected" == "$actual" ]'
|
||||||
|
|
||||||
selftest:
|
selftest:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -62,7 +85,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@V27
|
uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -71,7 +94,7 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: 'nix develop --command dotnet build --no-restore --configuration Release'
|
run: 'nix develop --command dotnet build --no-restore --configuration Release'
|
||||||
- name: Test using self
|
- name: Test using self
|
||||||
run: 'nix develop --command dotnet exec ./WoofWare.NUnitTestRunner/bin/Release/net8.0/WoofWare.NUnitTestRunner.dll ./Consumer/bin/Release/net8.0/Consumer.dll --trx TrxOut/out.trx'
|
run: 'nix develop --command dotnet exec ./WoofWare.NUnitTestRunner/bin/Release/net6.0/WoofWare.NUnitTestRunner.dll ./Consumer/bin/Release/net8.0/Consumer.dll --trx TrxOut/out.trx'
|
||||||
- name: Parse Trx files
|
- name: Parse Trx files
|
||||||
uses: NasAmin/trx-parser@v0.6.0
|
uses: NasAmin/trx-parser@v0.6.0
|
||||||
if: always()
|
if: always()
|
||||||
@@ -90,7 +113,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@V27
|
uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -107,12 +130,14 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@V27
|
uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build
|
- name: Build
|
||||||
run: nix build
|
run: nix build
|
||||||
|
- name: Reproducibility check
|
||||||
|
run: nix build --rebuild
|
||||||
|
|
||||||
check-dotnet-format:
|
check-dotnet-format:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -120,7 +145,7 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@V27
|
uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -133,7 +158,7 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@V27
|
uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -146,7 +171,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@V27
|
uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -159,7 +184,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@V27
|
uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -173,7 +198,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
fetch-depth: 0 # so that NerdBank.GitVersioning has access to history
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@V27
|
uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -215,59 +240,155 @@ jobs:
|
|||||||
# Verify that there is exactly one nupkg in the artifact that would be NuGet published
|
# Verify that there is exactly one nupkg in the artifact that would be NuGet published
|
||||||
run: if [[ $(find packed-tool -maxdepth 1 -name 'WoofWare.NUnitTestRunner.*.nupkg' -printf c | wc -c) -ne "1" ]]; then exit 1; fi
|
run: if [[ $(find packed-tool -maxdepth 1 -name 'WoofWare.NUnitTestRunner.*.nupkg' -printf c | wc -c) -ne "1" ]]; then exit 1; fi
|
||||||
|
|
||||||
github-release-tool-dry-run:
|
all-required-checks-complete:
|
||||||
needs: [nuget-pack]
|
if: ${{ always() }}
|
||||||
|
needs: [github-release-dry-run, check-dotnet-format, check-nix-format, build, build-nix, linkcheck, flake-check, analyzers, nuget-pack, expected-pack, selftest-intended-failures, selftest]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: G-Research/common-actions/check-required-lite@2b7dc49cb14f3344fbe6019c14a31165e258c059
|
||||||
- name: Download NuGet artifact (lib)
|
with:
|
||||||
|
needs-context: ${{ toJSON(needs) }}
|
||||||
|
|
||||||
|
attestation-lib:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [all-required-checks-complete]
|
||||||
|
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: Download NuGet artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nuget-package-lib
|
name: nuget-package-lib
|
||||||
- name: Download NuGet artifact (tool)
|
path: packed
|
||||||
|
- name: Attest Build Provenance
|
||||||
|
uses: actions/attest-build-provenance@7668571508540a607bdfd90a87a560489fe372eb # v2.1.0
|
||||||
|
with:
|
||||||
|
subject-path: "packed/*.nupkg"
|
||||||
|
|
||||||
|
attestation-tool:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [all-required-checks-complete]
|
||||||
|
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: Download NuGet artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nuget-package-tool
|
name: nuget-package-tool
|
||||||
- name: Tag and release tool
|
path: packed
|
||||||
env:
|
- name: Attest Build Provenance
|
||||||
DRY_RUN: 1
|
uses: actions/attest-build-provenance@7668571508540a607bdfd90a87a560489fe372eb # v2.1.0
|
||||||
GITHUB_TOKEN: mock-token
|
with:
|
||||||
run: sh .github/workflows/tag.sh
|
subject-path: "packed/*.nupkg"
|
||||||
|
|
||||||
all-required-checks-complete:
|
nuget-publish-lib:
|
||||||
needs: [check-dotnet-format, check-nix-format, build, build-nix, linkcheck, flake-check, analyzers, nuget-pack, expected-pack, github-release-tool-dry-run]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- run: echo "All required checks complete."
|
|
||||||
|
|
||||||
nuget-publish:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
||||||
needs: [all-required-checks-complete]
|
needs: [all-required-checks-complete]
|
||||||
environment: main-deploy
|
environment: main-deploy
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@V27
|
uses: cachix/install-nix-action@v30
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Download NuGet artifact (lib)
|
- name: Download NuGet artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nuget-package-lib
|
name: nuget-package-lib
|
||||||
path: packed-lib
|
path: packed
|
||||||
- name: Publish to NuGet (lib)
|
- name: Identify .NET
|
||||||
run: nix develop --command dotnet nuget push "packed-lib/WoofWare.NUnitTestRunner.Lib.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
id: identify-dotnet
|
||||||
- name: Download NuGet artifact (tool)
|
run: nix develop --command bash -c "echo dotnet=$(which dotnet) >> $GITHUB_OUTPUT"
|
||||||
|
- name: Publish NuGet package
|
||||||
|
uses: G-Research/common-actions/publish-nuget@2b7dc49cb14f3344fbe6019c14a31165e258c059
|
||||||
|
with:
|
||||||
|
package-name: WoofWare.NUnitTestRunner.Lib
|
||||||
|
nuget-key: ${{ secrets.NUGET_API_KEY }}
|
||||||
|
nupkg-dir: packed/
|
||||||
|
dotnet: ${{ steps.identify-dotnet.outputs.dotnet }}
|
||||||
|
|
||||||
|
nuget-publish-tool:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
||||||
|
needs: [all-required-checks-complete]
|
||||||
|
environment: main-deploy
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install Nix
|
||||||
|
uses: cachix/install-nix-action@v30
|
||||||
|
with:
|
||||||
|
extra_nix_config: |
|
||||||
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Download NuGet artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nuget-package-tool
|
name: nuget-package-tool
|
||||||
path: packed-tool
|
path: packed
|
||||||
- name: Publish to NuGet (tool)
|
- name: Identify .NET
|
||||||
run: nix develop --command dotnet nuget push "packed-tool/WoofWare.NUnitTestRunner.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
id: identify-dotnet
|
||||||
|
run: nix develop --command bash -c "echo dotnet=$(which dotnet) >> $GITHUB_OUTPUT"
|
||||||
|
- name: Publish NuGet package
|
||||||
|
uses: G-Research/common-actions/publish-nuget@2b7dc49cb14f3344fbe6019c14a31165e258c059
|
||||||
|
with:
|
||||||
|
package-name: WoofWare.NUnitTestRunner
|
||||||
|
nuget-key: ${{ secrets.NUGET_API_KEY }}
|
||||||
|
nupkg-dir: packed/
|
||||||
|
dotnet: ${{ steps.identify-dotnet.outputs.dotnet }}
|
||||||
|
|
||||||
github-release-tool:
|
github-release-dry-run:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
artifact:
|
||||||
|
- nuget-package-tool
|
||||||
|
- nuget-package-lib
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [nuget-pack]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Download NuGet artifact (tool)
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.artifact }}
|
||||||
|
- name: Compute package path
|
||||||
|
id: compute-path
|
||||||
|
run: |
|
||||||
|
find . -maxdepth 1 -type f -name 'WoofWare.NUnitTestRunner.*.nupkg' -exec sh -c 'echo "output=$(basename "$1")" >> $GITHUB_OUTPUT' shell {} \;
|
||||||
|
- name: Compute tag name
|
||||||
|
id: compute-tag
|
||||||
|
env:
|
||||||
|
NUPKG_PATH: ${{ steps.compute-path.outputs.output }}
|
||||||
|
run: echo "output=$(basename "$NUPKG_PATH" .nupkg)" >> $GITHUB_OUTPUT
|
||||||
|
- name: Tag and release
|
||||||
|
uses: G-Research/common-actions/github-release@9b51229eed6e1de78c37d0f17602f9570c074c3d
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
target-commitish: ${{ github.sha }}
|
||||||
|
tag: ${{ steps.compute-tag.outputs.output }}
|
||||||
|
binary-contents: ${{ steps.compute-path.outputs.output }}
|
||||||
|
dry-run: true
|
||||||
|
|
||||||
|
github-release:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
artifact:
|
||||||
|
- nuget-package-tool
|
||||||
|
- nuget-package-lib
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }}
|
||||||
needs: [all-required-checks-complete]
|
needs: [all-required-checks-complete]
|
||||||
@@ -279,12 +400,20 @@ jobs:
|
|||||||
- name: Download NuGet artifact (tool)
|
- name: Download NuGet artifact (tool)
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: nuget-package-tool
|
name: ${{ matrix.artifact }}
|
||||||
- name: Download NuGet artifact (lib)
|
- name: Compute package path
|
||||||
uses: actions/download-artifact@v4
|
id: compute-path
|
||||||
with:
|
run: |
|
||||||
name: nuget-package-lib
|
find . -maxdepth 1 -type f -name 'WoofWare.NUnitTestRunner.*.nupkg' -exec sh -c 'echo "output=$(basename "$1")" >> $GITHUB_OUTPUT' shell {} \;
|
||||||
- name: Tag and release plugin
|
- name: Compute tag name
|
||||||
|
id: compute-tag
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
NUPKG_PATH: ${{ steps.compute-path.outputs.output }}
|
||||||
run: sh .github/workflows/tag.sh
|
run: echo "output=$(basename "$NUPKG_PATH" .nupkg)" >> $GITHUB_OUTPUT
|
||||||
|
- name: Tag and release
|
||||||
|
uses: G-Research/common-actions/github-release@9b51229eed6e1de78c37d0f17602f9570c074c3d # TODO: set this to a prod version
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
target-commitish: ${{ github.sha }}
|
||||||
|
tag: ${{ steps.compute-tag.outputs.output }}
|
||||||
|
binary-contents: ${{ steps.compute-path.outputs.output }}
|
||||||
|
54
.github/workflows/flake_update.yaml
vendored
Normal file
54
.github/workflows/flake_update.yaml
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/github-workflow.json
|
||||||
|
name: Weekly Nix Flake Update
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0' # Runs at 00:00 every Sunday
|
||||||
|
workflow_dispatch: # Allows manual triggering
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-nix-flake:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Nix
|
||||||
|
uses: DeterminateSystems/nix-installer-action@main
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Update Nix flake
|
||||||
|
run: 'nix flake update'
|
||||||
|
|
||||||
|
- name: Build fetch-deps
|
||||||
|
run: 'nix build ".#default.fetch-deps"'
|
||||||
|
|
||||||
|
- name: Run fetch-deps
|
||||||
|
run: ./result nix/deps.json
|
||||||
|
|
||||||
|
- name: Format
|
||||||
|
run: 'nix develop --command alejandra .'
|
||||||
|
|
||||||
|
- name: Create token
|
||||||
|
id: generate-token
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
with:
|
||||||
|
# https://github.com/actions/create-github-app-token/issues/136
|
||||||
|
app-id: ${{ secrets.APP_ID }}
|
||||||
|
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Raise pull request
|
||||||
|
uses: Smaug123/commit-action@cc25e6d80a796c49669dda4a0aa36c54c573983d
|
||||||
|
id: cpr
|
||||||
|
with:
|
||||||
|
bearer-token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
pr-title: "Upgrade Nix flake and deps"
|
||||||
|
|
||||||
|
- name: Enable Pull Request Automerge
|
||||||
|
if: ${{ steps.cpr.outputs.pull-request-number }}
|
||||||
|
uses: peter-evans/enable-pull-request-automerge@v3
|
||||||
|
with:
|
||||||
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
pull-request-number: ${{ steps.cpr.outputs.pull-request-number }}
|
||||||
|
merge-method: squash
|
124
.github/workflows/tag.sh
vendored
124
.github/workflows/tag.sh
vendored
@@ -1,124 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
echo "Dry-run? $DRY_RUN!"
|
|
||||||
|
|
||||||
find . -maxdepth 1 -type f ! -name "$(printf "*\n*")" -name '*.nupkg' | while IFS= read -r file
|
|
||||||
do
|
|
||||||
tag=$(basename "$file" .nupkg)
|
|
||||||
git tag "$tag"
|
|
||||||
${DRY_RUN:+echo} git push origin "$tag"
|
|
||||||
done
|
|
||||||
|
|
||||||
export TAG
|
|
||||||
TAG=$(find . -maxdepth 1 -type f -name 'WoofWare.NUnitTestRunner.*.nupkg' -exec sh -c 'basename "$1" .nupkg' shell {} \; | grep -v Lib)
|
|
||||||
|
|
||||||
case "$TAG" in
|
|
||||||
*"
|
|
||||||
"*)
|
|
||||||
echo "Error: TAG contains a newline; multiple tools found."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# target_commitish empty indicates the repo default branch
|
|
||||||
IS_PRERELEASE="false"
|
|
||||||
if [ "${TAG#*prerelease}" != "$TAG" ]; then
|
|
||||||
IS_PRERELEASE="true"
|
|
||||||
fi
|
|
||||||
curl_body='{"tag_name":"'"$TAG"'","target_commitish":"","name":"'"$TAG"'","draft":false,"prerelease":'"$IS_PRERELEASE"',"generate_release_notes":false}'
|
|
||||||
|
|
||||||
echo "cURL body: $curl_body"
|
|
||||||
|
|
||||||
failed_output=$(cat <<'EOF'
|
|
||||||
{
|
|
||||||
"message": "Validation Failed",
|
|
||||||
"errors": [
|
|
||||||
{
|
|
||||||
"resource": "Release",
|
|
||||||
"code": "already_exists",
|
|
||||||
"field": "tag_name"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"documentation_url": "https://docs.github.com/rest/releases/releases#create-a-release"
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
success_output=$(cat <<'EOF'
|
|
||||||
{
|
|
||||||
"url": "https://api.github.com/repos/Smaug123/unofficial-nunit-runner/releases/158152116",
|
|
||||||
"assets_url": "https://api.github.com/repos/Smaug123/unofficial-nunit-runner/releases/158152116/assets",
|
|
||||||
"upload_url": "https://uploads.github.com/repos/Smaug123/unofficial-nunit-runner/releases/158152116/assets{?name,label}",
|
|
||||||
"html_url": "https://github.com/Smaug123/unofficial-nunit-runner/releases/tag/WoofWare.NUnitTestRunner.2.1.30",
|
|
||||||
"id": 158152116,
|
|
||||||
"author": {
|
|
||||||
"login": "github-actions[bot]",
|
|
||||||
"id": 41898282,
|
|
||||||
"node_id": "MDM6Qm90NDE4OTgyODI=",
|
|
||||||
"avatar_url": "https://avatars.githubusercontent.com/in/15368?v=4",
|
|
||||||
"gravatar_id": "",
|
|
||||||
"url": "https://api.github.com/users/github-actions%5Bbot%5D",
|
|
||||||
"html_url": "https://github.com/apps/github-actions",
|
|
||||||
"followers_url": "https://api.github.com/users/github-actions%5Bbot%5D/followers",
|
|
||||||
"following_url": "https://api.github.com/users/github-actions%5Bbot%5D/following{/other_user}",
|
|
||||||
"gists_url": "https://api.github.com/users/github-actions%5Bbot%5D/gists{/gist_id}",
|
|
||||||
"starred_url": "https://api.github.com/users/github-actions%5Bbot%5D/starred{/owner}{/repo}",
|
|
||||||
"subscriptions_url": "https://api.github.com/users/github-actions%5Bbot%5D/subscriptions",
|
|
||||||
"organizations_url": "https://api.github.com/users/github-actions%5Bbot%5D/orgs",
|
|
||||||
"repos_url": "https://api.github.com/users/github-actions%5Bbot%5D/repos",
|
|
||||||
"events_url": "https://api.github.com/users/github-actions%5Bbot%5D/events{/privacy}",
|
|
||||||
"received_events_url": "https://api.github.com/users/github-actions%5Bbot%5D/received_events",
|
|
||||||
"type": "Bot",
|
|
||||||
"site_admin": false
|
|
||||||
},
|
|
||||||
"node_id": "RE_kwDOJfksgc4JbTW0",
|
|
||||||
"tag_name": "WoofWare.NUnitTestRunner.2.1.30",
|
|
||||||
"target_commitish": "main",
|
|
||||||
"name": "WoofWare.NUnitTestRunner.2.1.30",
|
|
||||||
"draft": false,
|
|
||||||
"prerelease": false,
|
|
||||||
"created_at": "2024-05-30T11:00:55Z",
|
|
||||||
"published_at": "2024-05-30T11:03:02Z",
|
|
||||||
"assets": [
|
|
||||||
|
|
||||||
],
|
|
||||||
"tarball_url": "https://api.github.com/repos/Smaug123/unofficial-nunit-runner/tarball/WoofWare.NUnitTestRunner.2.1.30",
|
|
||||||
"zipball_url": "https://api.github.com/repos/Smaug123/unofficial-nunit-runner/zipball/WoofWare.NUnitTestRunner.2.1.30",
|
|
||||||
"body": null
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
HANDLE_OUTPUT=''
|
|
||||||
handle_error() {
|
|
||||||
ERROR_OUTPUT="$1"
|
|
||||||
exit_message=$(echo "$ERROR_OUTPUT" | jq -r --exit-status 'if .errors | length == 1 then .errors[0].code else null end')
|
|
||||||
if [ "$exit_message" = "already_exists" ] ; then
|
|
||||||
HANDLE_OUTPUT="Did not create GitHub release because it already exists at this version."
|
|
||||||
else
|
|
||||||
echo "Unexpected error output from curl: $(cat curl_output.json)"
|
|
||||||
echo "JQ output: $(exit_message)"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
run_tests() {
|
|
||||||
handle_error "$failed_output"
|
|
||||||
if [ "$HANDLE_OUTPUT" != "Did not create GitHub release because it already exists at this version." ]; then
|
|
||||||
echo "Bad output from handler: $HANDLE_OUTPUT"
|
|
||||||
exit 3
|
|
||||||
fi
|
|
||||||
HANDLE_OUTPUT=''
|
|
||||||
echo "Tests passed."
|
|
||||||
}
|
|
||||||
|
|
||||||
run_tests
|
|
||||||
|
|
||||||
if [ "$DRY_RUN" != 1 ] ; then
|
|
||||||
if curl --fail-with-body -L -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GITHUB_TOKEN" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/Smaug123/unofficial-nunit-runner/releases -d "$curl_body" > curl_output.json; then
|
|
||||||
echo "Curl succeeded."
|
|
||||||
else
|
|
||||||
handle_error "$(cat curl_output.json)"
|
|
||||||
echo "$HANDLE_OUTPUT"
|
|
||||||
fi
|
|
||||||
fi
|
|
@@ -1,8 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<IsTestProject>true</IsTestProject>
|
<IsTestProject>true</IsTestProject>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -10,7 +9,11 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="NoAttribute.fs" />
|
<Compile Include="NoAttribute.fs" />
|
||||||
<Compile Include="Inconclusive.fs" />
|
<Compile Include="Inconclusive.fs" />
|
||||||
|
<Compile Include="RunSubProcess.fs" />
|
||||||
|
<Compile Include="TestNonParallel.fs" />
|
||||||
<Compile Include="TestParallel.fs" />
|
<Compile Include="TestParallel.fs" />
|
||||||
|
<Compile Include="TestParallelIndividualTest.fs" />
|
||||||
|
<Compile Include="TestStdout.fs" />
|
||||||
<Compile Include="TestParameterisedFixture.fs" />
|
<Compile Include="TestParameterisedFixture.fs" />
|
||||||
<Compile Include="TestSetUp.fs" />
|
<Compile Include="TestSetUp.fs" />
|
||||||
<Compile Include="TestValues.fs" />
|
<Compile Include="TestValues.fs" />
|
||||||
@@ -23,10 +26,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FsUnit" Version="6.0.0" />
|
<PackageReference Include="FsUnit" Version="7.0.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/>
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
|
||||||
<PackageReference Include="NUnit" Version="4.1.0"/>
|
<PackageReference Include="NUnit" Version="4.3.2"/>
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
45
Consumer/RunSubProcess.fs
Normal file
45
Consumer/RunSubProcess.fs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
namespace Consumer
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Diagnostics
|
||||||
|
open System.IO
|
||||||
|
open System.IO.Compression
|
||||||
|
open System.Text
|
||||||
|
open NUnit.Framework
|
||||||
|
open FsUnitTyped
|
||||||
|
|
||||||
|
[<TestFixture>]
|
||||||
|
module RunSubProcess =
|
||||||
|
[<Test>]
|
||||||
|
let ``Run a subprocess`` () =
|
||||||
|
let exe = "/bin/bash"
|
||||||
|
let args = [ "-c" ; "echo hi >&2 && echo bye" ]
|
||||||
|
let workingDir = None
|
||||||
|
|
||||||
|
let psi =
|
||||||
|
ProcessStartInfo (
|
||||||
|
exe,
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
WorkingDirectory = Option.toObj workingDir
|
||||||
|
)
|
||||||
|
|
||||||
|
for arg in args do
|
||||||
|
psi.ArgumentList.Add arg
|
||||||
|
|
||||||
|
psi.EnvironmentVariables.Add ("THING", Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "hi"))
|
||||||
|
let stderr = StringBuilder ()
|
||||||
|
use proc = new Process (StartInfo = psi)
|
||||||
|
proc.OutputDataReceived.Add (fun e -> printfn $"%s{e.Data}")
|
||||||
|
|
||||||
|
proc.ErrorDataReceived.Add (fun e ->
|
||||||
|
eprintfn $"%s{e.Data}"
|
||||||
|
stderr.AppendLine e.Data |> ignore
|
||||||
|
)
|
||||||
|
|
||||||
|
proc.Start () |> shouldEqual true
|
||||||
|
proc.BeginOutputReadLine ()
|
||||||
|
proc.BeginErrorReadLine ()
|
||||||
|
|
||||||
|
proc.WaitForExit ()
|
19
Consumer/TestNonParallel.fs
Normal file
19
Consumer/TestNonParallel.fs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
namespace Consumer
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Threading
|
||||||
|
open NUnit.Framework
|
||||||
|
open FsUnitTyped
|
||||||
|
|
||||||
|
[<TestFixture>]
|
||||||
|
[<NonParallelizable>]
|
||||||
|
module TestNonParallel =
|
||||||
|
let defaults = List.init 40 id
|
||||||
|
let lock = ref 0
|
||||||
|
|
||||||
|
[<TestCaseSource(nameof defaults)>]
|
||||||
|
let ``Default thing, but not parallel`` (i : int) =
|
||||||
|
Interlocked.Increment lock |> shouldEqual 1
|
||||||
|
Thread.Sleep (TimeSpan.FromMilliseconds (float i))
|
||||||
|
lock.Value <- 0
|
||||||
|
i |> shouldEqual i
|
@@ -1,5 +1,7 @@
|
|||||||
namespace Consumer
|
namespace Consumer
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Threading
|
||||||
open NUnit.Framework
|
open NUnit.Framework
|
||||||
open FsUnitTyped
|
open FsUnitTyped
|
||||||
|
|
||||||
@@ -7,43 +9,58 @@ open FsUnitTyped
|
|||||||
[<Parallelizable>]
|
[<Parallelizable>]
|
||||||
module TestParallelDefault =
|
module TestParallelDefault =
|
||||||
|
|
||||||
let defaults = List.init 100 id
|
let defaults = List.init 60 id
|
||||||
|
|
||||||
[<TestCaseSource(nameof defaults)>]
|
[<TestCaseSource(nameof defaults)>]
|
||||||
let ``Default thing`` (i : int) = i |> shouldEqual i
|
let ``Default thing, no scope`` (i : int) =
|
||||||
|
Console.WriteLine i
|
||||||
|
Thread.Sleep (TimeSpan.FromMilliseconds (float i))
|
||||||
|
i |> shouldEqual i
|
||||||
|
|
||||||
[<TestFixture>]
|
[<TestFixture>]
|
||||||
[<Parallelizable(ParallelScope.All)>]
|
[<Parallelizable(ParallelScope.All)>]
|
||||||
module TestParallelAllScope =
|
module TestParallelAllScope =
|
||||||
|
|
||||||
let defaults = List.init 100 id
|
let defaults = List.init 60 id
|
||||||
|
|
||||||
[<TestCaseSource(nameof defaults)>]
|
[<TestCaseSource(nameof defaults)>]
|
||||||
let ``Default thing`` (i : int) = i |> shouldEqual i
|
let ``Thing, all scope`` (i : int) =
|
||||||
|
Console.WriteLine i
|
||||||
|
Thread.Sleep (TimeSpan.FromMilliseconds (float i))
|
||||||
|
i |> shouldEqual i
|
||||||
|
|
||||||
[<TestFixture>]
|
[<TestFixture>]
|
||||||
[<Parallelizable(ParallelScope.Self)>]
|
[<Parallelizable(ParallelScope.Self)>]
|
||||||
module TestParallelSelfScope =
|
module TestParallelSelfScope =
|
||||||
|
|
||||||
let defaults = List.init 100 id
|
let defaults = List.init 60 id
|
||||||
|
|
||||||
[<TestCaseSource(nameof defaults)>]
|
[<TestCaseSource(nameof defaults)>]
|
||||||
let ``Default thing`` (i : int) = i |> shouldEqual i
|
let ``Thing, self scope`` (i : int) =
|
||||||
|
Console.WriteLine i
|
||||||
|
Thread.Sleep (TimeSpan.FromMilliseconds (float i))
|
||||||
|
i |> shouldEqual i
|
||||||
|
|
||||||
[<TestFixture>]
|
[<TestFixture>]
|
||||||
[<Parallelizable(ParallelScope.Children)>]
|
[<Parallelizable(ParallelScope.Children)>]
|
||||||
module TestParallelChildrenScope =
|
module TestParallelChildrenScope =
|
||||||
|
|
||||||
let defaults = List.init 100 id
|
let defaults = List.init 60 id
|
||||||
|
|
||||||
[<TestCaseSource(nameof defaults)>]
|
[<TestCaseSource(nameof defaults)>]
|
||||||
let ``Default thing`` (i : int) = i |> shouldEqual i
|
let ``Thing, children scope`` (i : int) =
|
||||||
|
Console.WriteLine i
|
||||||
|
Thread.Sleep (TimeSpan.FromMilliseconds (float i))
|
||||||
|
i |> shouldEqual i
|
||||||
|
|
||||||
[<TestFixture>]
|
[<TestFixture>]
|
||||||
[<Parallelizable(ParallelScope.Fixtures)>]
|
[<Parallelizable(ParallelScope.Fixtures)>]
|
||||||
module TestParallelFixturesScope =
|
module TestParallelFixturesScope =
|
||||||
|
|
||||||
let defaults = List.init 100 id
|
let defaults = List.init 60 id
|
||||||
|
|
||||||
[<TestCaseSource(nameof defaults)>]
|
[<TestCaseSource(nameof defaults)>]
|
||||||
let ``Default thing`` (i : int) = i |> shouldEqual i
|
let ``Thing, fixtures scope`` (i : int) =
|
||||||
|
Console.WriteLine i
|
||||||
|
Thread.Sleep (TimeSpan.FromMilliseconds (float i))
|
||||||
|
i |> shouldEqual i
|
||||||
|
59
Consumer/TestParallelIndividualTest.fs
Normal file
59
Consumer/TestParallelIndividualTest.fs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
namespace Consumer
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Collections.Concurrent
|
||||||
|
open System.Threading
|
||||||
|
open NUnit.Framework
|
||||||
|
open FsUnitTyped
|
||||||
|
|
||||||
|
// These tests are flaky if the bug https://github.com/Smaug123/unofficial-nunit-runner/issues/168 is unfixed.
|
||||||
|
[<TestFixture>]
|
||||||
|
module TestParallelIndividualTest =
|
||||||
|
|
||||||
|
type private Transitions =
|
||||||
|
| Started of int
|
||||||
|
| LockAcquired of int
|
||||||
|
| Exited of int
|
||||||
|
|
||||||
|
let locker = obj ()
|
||||||
|
let private sequence = ConcurrentQueue<Transitions> ()
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
[<Parallelizable(ParallelScope.None)>]
|
||||||
|
let ``does not run in parallel`` () =
|
||||||
|
sequence.Enqueue (Transitions.Started 0)
|
||||||
|
let entered = Monitor.TryEnter (locker, TimeSpan.Zero)
|
||||||
|
|
||||||
|
if entered then
|
||||||
|
sequence.Enqueue (Transitions.LockAcquired 0)
|
||||||
|
Monitor.Exit locker
|
||||||
|
sequence.Enqueue (Transitions.Exited 0)
|
||||||
|
else
|
||||||
|
sequence.Enqueue (Transitions.Exited 0)
|
||||||
|
failwith "failed to acquire the lock"
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``unrestricted parallelism`` () =
|
||||||
|
sequence.Enqueue (Transitions.Started 1)
|
||||||
|
let entered = Monitor.TryEnter (locker, TimeSpan.Zero)
|
||||||
|
|
||||||
|
if entered then
|
||||||
|
sequence.Enqueue (Transitions.LockAcquired 1)
|
||||||
|
Monitor.Exit locker
|
||||||
|
sequence.Enqueue (Transitions.Exited 1)
|
||||||
|
else
|
||||||
|
sequence.Enqueue (Transitions.Exited 1)
|
||||||
|
failwith "failed to acquire the lock"
|
||||||
|
|
||||||
|
[<OneTimeTearDown>]
|
||||||
|
let ``It worked`` () =
|
||||||
|
let sequence = sequence |> Seq.toList
|
||||||
|
|
||||||
|
let allowed n =
|
||||||
|
[ Transitions.Started n ; Transitions.LockAcquired n ; Transitions.Exited n ]
|
||||||
|
|
||||||
|
if sequence <> allowed 0 @ allowed 1 && sequence <> allowed 1 @ allowed 0 then
|
||||||
|
let s = sequence |> Seq.map string<Transitions> |> String.concat "\n"
|
||||||
|
failwith $"Unexpected sequence!\n%s{s}"
|
||||||
|
|
||||||
|
()
|
@@ -1,5 +1,6 @@
|
|||||||
namespace Consumer
|
namespace Consumer
|
||||||
|
|
||||||
|
open System
|
||||||
open FsUnitTyped
|
open FsUnitTyped
|
||||||
open System.Threading
|
open System.Threading
|
||||||
open NUnit.Framework
|
open NUnit.Framework
|
||||||
@@ -11,6 +12,8 @@ module TestSetUp =
|
|||||||
|
|
||||||
[<OneTimeSetUp>]
|
[<OneTimeSetUp>]
|
||||||
let oneTimeSetUp () =
|
let oneTimeSetUp () =
|
||||||
|
Console.WriteLine "I'm being set up for the first time!"
|
||||||
|
|
||||||
if Interlocked.Increment haveOneTimeSetUp <> 1 then
|
if Interlocked.Increment haveOneTimeSetUp <> 1 then
|
||||||
failwith "one time setup happened more than once"
|
failwith "one time setup happened more than once"
|
||||||
|
|
||||||
@@ -22,12 +25,14 @@ module TestSetUp =
|
|||||||
|
|
||||||
[<SetUp>]
|
[<SetUp>]
|
||||||
let setUp () =
|
let setUp () =
|
||||||
|
Console.WriteLine "It's a set-up!"
|
||||||
haveOneTimeSetUp.Value |> shouldEqual 1
|
haveOneTimeSetUp.Value |> shouldEqual 1
|
||||||
let newId = Interlocked.Increment setUpTimes
|
let newId = Interlocked.Increment setUpTimes
|
||||||
lock setUpTimesSeen (fun () -> setUpTimesSeen.Add newId)
|
lock setUpTimesSeen (fun () -> setUpTimesSeen.Add newId)
|
||||||
|
|
||||||
[<TearDown>]
|
[<TearDown>]
|
||||||
let tearDown () =
|
let tearDown () =
|
||||||
|
Console.WriteLine "I'm a tear-down!"
|
||||||
let newId = Interlocked.Increment tearDownTimes
|
let newId = Interlocked.Increment tearDownTimes
|
||||||
lock tearDownTimesSeen (fun () -> tearDownTimesSeen.Add newId)
|
lock tearDownTimesSeen (fun () -> tearDownTimesSeen.Add newId)
|
||||||
|
|
||||||
@@ -35,19 +40,23 @@ module TestSetUp =
|
|||||||
|
|
||||||
[<OneTimeTearDown>]
|
[<OneTimeTearDown>]
|
||||||
let oneTimeTearDown () =
|
let oneTimeTearDown () =
|
||||||
|
Console.WriteLine "I'm being torn down, finally!"
|
||||||
|
|
||||||
if Interlocked.Increment haveOneTimeTearDown <> 1 then
|
if Interlocked.Increment haveOneTimeTearDown <> 1 then
|
||||||
failwith "one time tear down happened more than once"
|
failwith "one time tear down happened more than once"
|
||||||
|
|
||||||
setUpTimesSeen
|
setUpTimesSeen
|
||||||
|> Seq.toList
|
|> Seq.toList
|
||||||
|
|> List.sort
|
||||||
// Six tests: one for Test, two for the TestCase, three for the Repeat.
|
// Six tests: one for Test, two for the TestCase, three for the Repeat.
|
||||||
|> shouldEqual [ 1..6 ]
|
|> shouldEqual [ 1..6 ]
|
||||||
|
|
||||||
tearDownTimesSeen |> Seq.toList |> shouldEqual [ 1..6 ]
|
tearDownTimesSeen |> Seq.toList |> List.sort |> shouldEqual [ 1..6 ]
|
||||||
|
|
||||||
[<Test>]
|
[<Test>]
|
||||||
let ``Test 1`` () =
|
let ``Test 1`` () =
|
||||||
haveOneTimeTearDown.Value |> shouldEqual 0
|
haveOneTimeTearDown.Value |> shouldEqual 0
|
||||||
|
Console.WriteLine "By the way, I'm test 1"
|
||||||
1 |> shouldEqual 1
|
1 |> shouldEqual 1
|
||||||
|
|
||||||
[<TestCase "h">]
|
[<TestCase "h">]
|
||||||
|
13
Consumer/TestStdout.fs
Normal file
13
Consumer/TestStdout.fs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Consumer
|
||||||
|
|
||||||
|
open System
|
||||||
|
open NUnit.Framework
|
||||||
|
|
||||||
|
[<TestFixture>]
|
||||||
|
module TestStdout =
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``Stdout is redirected`` () =
|
||||||
|
Console.Out.WriteLine "Hi!"
|
||||||
|
Console.WriteLine "Hi! part 2"
|
||||||
|
Console.Error.WriteLine "Bye!"
|
@@ -86,14 +86,42 @@ module TestValues =
|
|||||||
|
|
||||||
[<OneTimeTearDown>]
|
[<OneTimeTearDown>]
|
||||||
let ``Values are all OK`` () =
|
let ``Values are all OK`` () =
|
||||||
seen1 |> Seq.toList |> shouldEqual [ true ; false ]
|
seen1 |> Seq.toList |> List.sort |> shouldEqual [ false ; true ]
|
||||||
seen2 |> Seq.toList |> shouldEqual [ (true, false) ; (false, true) ]
|
|
||||||
seen3 |> Seq.toList |> shouldEqual [ (88, box 29) ; (31, box 0) ]
|
seen2
|
||||||
seen4 |> Seq.toList |> shouldEqual [ ("hi", box "ohh") ; ("bye", null) ]
|
|> Seq.toList
|
||||||
seen5 |> Seq.toList |> shouldEqual [ (88, box 29) ; (31, box 29) ]
|
|> List.sort
|
||||||
seen6 |> Seq.toList |> shouldEqual [ ("hi", box "ohh") ; ("bye", box "ohh") ]
|
|> shouldEqual [ (false, true) ; (true, false) ]
|
||||||
seen7 |> Seq.toList |> shouldEqual [ (88, box 29) ; (31, box 29) ]
|
|
||||||
seen8 |> Seq.toList |> shouldEqual [ ("hi", box "ohh") ; ("bye", box "ohh") ]
|
seen3
|
||||||
|
|> Seq.toList
|
||||||
|
|> List.sortBy fst
|
||||||
|
|> shouldEqual [ (31, box 0) ; (88, box 29) ]
|
||||||
|
|
||||||
|
seen4
|
||||||
|
|> Seq.toList
|
||||||
|
|> List.sortBy fst
|
||||||
|
|> shouldEqual [ ("bye", null) ; ("hi", box "ohh") ]
|
||||||
|
|
||||||
|
seen5
|
||||||
|
|> Seq.toList
|
||||||
|
|> List.sortBy fst
|
||||||
|
|> shouldEqual [ (31, box 29) ; (88, box 29) ]
|
||||||
|
|
||||||
|
seen6
|
||||||
|
|> Seq.toList
|
||||||
|
|> List.sortBy fst
|
||||||
|
|> shouldEqual [ ("bye", box "ohh") ; ("hi", box "ohh") ]
|
||||||
|
|
||||||
|
seen7
|
||||||
|
|> Seq.toList
|
||||||
|
|> List.sortBy fst
|
||||||
|
|> shouldEqual [ (31, box 29) ; (88, box 29) ]
|
||||||
|
|
||||||
|
seen8
|
||||||
|
|> Seq.toList
|
||||||
|
|> List.sortBy fst
|
||||||
|
|> shouldEqual [ ("bye", box "ohh") ; ("hi", box "ohh") ]
|
||||||
|
|
||||||
seen9
|
seen9
|
||||||
|> Seq.toList
|
|> Seq.toList
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
<WarnOn>FS3388,FS3559</WarnOn>
|
<WarnOn>FS3388,FS3559</WarnOn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Nerdbank.GitVersioning" Version="3.6.139" PrivateAssets="all"/>
|
<PackageReference Include="Nerdbank.GitVersioning" Version="3.7.112" PrivateAssets="all"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Condition="'$(GITHUB_ACTION)' != ''">
|
<PropertyGroup Condition="'$(GITHUB_ACTION)' != ''">
|
||||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||||
|
20
FailingConsumer/FailingConsumer.fsproj
Normal file
20
FailingConsumer/FailingConsumer.fsproj
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="TestInsufficientArgs.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FsUnit" Version="7.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
|
||||||
|
<PackageReference Include="NUnit" Version="4.3.2"/>
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
9
FailingConsumer/TestInsufficientArgs.fs
Normal file
9
FailingConsumer/TestInsufficientArgs.fs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace FailingConsumer
|
||||||
|
|
||||||
|
open NUnit.Framework
|
||||||
|
|
||||||
|
[<TestFixture>]
|
||||||
|
module TestInsufficientArgs =
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let foo (_ : int) = ()
|
1
FailingConsumer/expected.txt
Normal file
1
FailingConsumer/expected.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo: had parameter count mismatch: expected 1, actual 0
|
@@ -12,5 +12,4 @@ However, we would recommend phrasing some of them differently, for maximum peace
|
|||||||
## Parallelism
|
## Parallelism
|
||||||
|
|
||||||
WoofWare.NUnitTestRunner has *limited* support for parallelism.
|
WoofWare.NUnitTestRunner has *limited* support for parallelism.
|
||||||
By default, we run tests serially; we may or may not respect the NUnit parallelism attributes to any given extent (but we will never incorrectly run tests in parallel).
|
By default, we run tests in parallel, taking half the available processors; we may or may not respect the NUnit parallelism attributes to any given extent that they tell us to be *more* parallel (but we will never incorrectly run tests in parallel).
|
||||||
For example, as of this writing, we do not run any tests in parallel (but the internal infrastructure is set up so that we will be able to do this soon).
|
|
||||||
|
99
WoofWare.NUnitTestRunner.Lib/Args.fs
Normal file
99
WoofWare.NUnitTestRunner.Lib/Args.fs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
namespace WoofWare.NUnitTestRunner
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.IO
|
||||||
|
|
||||||
|
[<AutoOpen>]
|
||||||
|
module internal Patterns =
|
||||||
|
let (|Key|_|) (start : string) (s : string) : string option =
|
||||||
|
if s.StartsWith (start + "=", StringComparison.Ordinal) then
|
||||||
|
s.Substring (start.Length + 1) |> Some
|
||||||
|
else
|
||||||
|
None
|
||||||
|
|
||||||
|
/// Represents how verbose the test runner's logging should be.
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
type LogLevel =
|
||||||
|
/// Don't log any information about the test run.
|
||||||
|
| Nothing
|
||||||
|
/// Log as much information as is available about the test run.
|
||||||
|
| Verbose
|
||||||
|
|
||||||
|
/// Arguments controlling the test runner itself (not the tests therein).
|
||||||
|
type Args =
|
||||||
|
{
|
||||||
|
/// The DLL containing the tests we'll reflectively discover and invoke.
|
||||||
|
Dll : FileInfo
|
||||||
|
/// If set, the output file into which we will write a TRX report. (We'll create parent directories as necessary.)
|
||||||
|
Trx : FileInfo option
|
||||||
|
/// Also contains the original string which specified the filter.
|
||||||
|
Filter : (string * Filter) option
|
||||||
|
/// How verbose to be with the test runner's own logging.
|
||||||
|
Logging : LogLevel
|
||||||
|
/// Maximum number of tests which can run concurrently. This setting overrides any LevelOfParallelism reflectively
|
||||||
|
/// extracted from the assembly under test.
|
||||||
|
LevelOfParallelism : int option
|
||||||
|
/// Abort if the test runner is running for longer than this timeout.
|
||||||
|
Timeout : TimeSpan option
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse `argv` into a structured Args.
|
||||||
|
static member Parse (args : string list) : Args =
|
||||||
|
match args with
|
||||||
|
| [] -> failwith "The first arg must be a positional arg, the DLL to test."
|
||||||
|
| dll :: args ->
|
||||||
|
|
||||||
|
let rec go
|
||||||
|
(trx : FileInfo option)
|
||||||
|
(filter : (string * Filter) option)
|
||||||
|
(logging : LogLevel option)
|
||||||
|
(par : int option)
|
||||||
|
(timeout : TimeSpan option)
|
||||||
|
(args : string list)
|
||||||
|
=
|
||||||
|
match args with
|
||||||
|
| [] ->
|
||||||
|
{
|
||||||
|
Dll = FileInfo dll
|
||||||
|
Trx = trx
|
||||||
|
Filter = filter
|
||||||
|
Logging = logging |> Option.defaultValue LogLevel.Nothing
|
||||||
|
LevelOfParallelism = par
|
||||||
|
Timeout = timeout
|
||||||
|
}
|
||||||
|
| Key "--filter" filterStr :: rest
|
||||||
|
| "--filter" :: filterStr :: rest ->
|
||||||
|
match filter with
|
||||||
|
| Some _ -> failwith "Two conflicting filters; you can only specify --filter once"
|
||||||
|
| None -> go trx (Some (filterStr, Filter.parse filterStr)) logging par timeout rest
|
||||||
|
| Key "--trx" trxStr :: rest
|
||||||
|
| "--trx" :: trxStr :: rest ->
|
||||||
|
match trx with
|
||||||
|
| Some _ -> failwith "Two conflicting TRX outputs; you can only specify --trx once"
|
||||||
|
| None -> go (Some (FileInfo trxStr)) filter logging par timeout rest
|
||||||
|
| Key "--verbose" verboseStr :: rest
|
||||||
|
| "--verbose" :: verboseStr :: rest ->
|
||||||
|
match logging with
|
||||||
|
| Some _ -> failwith "Two conflicting --verbose outputs; you can only specify --verbose once"
|
||||||
|
| None ->
|
||||||
|
let verbose =
|
||||||
|
if Boolean.Parse verboseStr then
|
||||||
|
LogLevel.Verbose
|
||||||
|
else
|
||||||
|
LogLevel.Nothing
|
||||||
|
|
||||||
|
go trx filter (Some verbose) par timeout rest
|
||||||
|
| Key "--parallelism" parStr :: rest
|
||||||
|
| "--parallelism" :: parStr :: rest ->
|
||||||
|
match par with
|
||||||
|
| Some _ -> failwith "Two conflicting --parallelism outputs; you can only specify --parallelism once"
|
||||||
|
| None -> go trx filter logging (Some (Int32.Parse parStr)) timeout rest
|
||||||
|
| Key "--timeout-seconds" timeoutStr :: rest
|
||||||
|
| "--timeout-seconds" :: timeoutStr :: rest ->
|
||||||
|
match timeout with
|
||||||
|
| Some _ ->
|
||||||
|
failwith "Two conflicting --timeout-seconds outputs; you can only specify --timeout-seconds once"
|
||||||
|
| None -> go trx filter logging par (Some (TimeSpan.FromSeconds (Int32.Parse timeoutStr |> float))) rest
|
||||||
|
| k :: _rest -> failwith $"Unrecognised arg %s{k}"
|
||||||
|
|
||||||
|
go None None None None None args
|
62
WoofWare.NUnitTestRunner.Lib/AssemblyLevelAttributes.fs
Normal file
62
WoofWare.NUnitTestRunner.Lib/AssemblyLevelAttributes.fs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
namespace WoofWare.NUnitTestRunner
|
||||||
|
|
||||||
|
open System.Reflection
|
||||||
|
|
||||||
|
/// Attributes at the assembly level which control the behaviour of NUnit.
|
||||||
|
type AssemblyLevelAttributes =
|
||||||
|
{
|
||||||
|
/// How many tests can be running at once, if anything's running in parallel.
|
||||||
|
Parallelism : int option
|
||||||
|
/// Whether the tests in this assembly can be parallelised at all.
|
||||||
|
Parallelizable : Parallelizable<AssemblyParallelScope> option
|
||||||
|
}
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module AssemblyLevelAttributes =
|
||||||
|
|
||||||
|
/// Reflectively obtain the values of any relevant assembly attributes.
|
||||||
|
let get (assy : Assembly) : AssemblyLevelAttributes =
|
||||||
|
((None, None), assy.CustomAttributes)
|
||||||
|
||> Seq.fold (fun (levelPar, par) attr ->
|
||||||
|
match attr.AttributeType.FullName with
|
||||||
|
| "NUnit.Framework.LevelOfParallelismAttribute" ->
|
||||||
|
let arg = attr.ConstructorArguments |> Seq.exactlyOne |> _.Value |> unbox<int>
|
||||||
|
|
||||||
|
match levelPar with
|
||||||
|
| None -> (Some arg, par)
|
||||||
|
| Some existing ->
|
||||||
|
failwith $"Assembly %s{assy.Location} declares parallelism %i{arg} and also %i{existing}"
|
||||||
|
| "NUnit.Framework.NonParallelizableAttribute" ->
|
||||||
|
match levelPar with
|
||||||
|
| None -> (Some 1, par)
|
||||||
|
| Some existing ->
|
||||||
|
failwith
|
||||||
|
$"Assembly %s{assy.Location} declares non-parallelizable and also parallelism %i{existing}"
|
||||||
|
| "NUnit.Framework.ParallelizableAttribute" ->
|
||||||
|
match par with
|
||||||
|
| Some _ -> failwith "Got multiple Parallelize attributes in assembly"
|
||||||
|
| None ->
|
||||||
|
match attr.ConstructorArguments |> Seq.toList with
|
||||||
|
| [] -> levelPar, Some (Parallelizable.Yes AssemblyParallelScope.Fixtures)
|
||||||
|
| [ v ] ->
|
||||||
|
match v.Value with
|
||||||
|
| :? int as v ->
|
||||||
|
match ParallelScope.ofInt v with
|
||||||
|
| ParallelScope.Fixtures ->
|
||||||
|
levelPar, Some (Parallelizable.Yes AssemblyParallelScope.Fixtures)
|
||||||
|
| ParallelScope.Children ->
|
||||||
|
levelPar, Some (Parallelizable.Yes AssemblyParallelScope.Children)
|
||||||
|
| ParallelScope.None -> levelPar, Some Parallelizable.No
|
||||||
|
| ParallelScope.All ->
|
||||||
|
failwith "ParallelScope.All is invalid on assemblies; only Fixtures or Children"
|
||||||
|
| ParallelScope.Self ->
|
||||||
|
failwith "ParallelScope.Self is invalid on assemblies; only Fixtures or Children"
|
||||||
|
| v -> failwith $"Unexpectedly non-int value %O{v} of parallel scope on assembly"
|
||||||
|
| _ -> failwith "unexpectedly got multiple args to Parallelizable on assembly"
|
||||||
|
| _ -> levelPar, par
|
||||||
|
)
|
||||||
|
|> fun (par, canPar) ->
|
||||||
|
{
|
||||||
|
Parallelizable = canPar
|
||||||
|
Parallelism = par
|
||||||
|
}
|
186
WoofWare.NUnitTestRunner.Lib/Context.fs
Normal file
186
WoofWare.NUnitTestRunner.Lib/Context.fs
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
namespace WoofWare.NUnitTestRunner
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Collections.Generic
|
||||||
|
open System.IO
|
||||||
|
open System.Reflection
|
||||||
|
open System.Runtime.Loader
|
||||||
|
open System.Text
|
||||||
|
open System.Threading
|
||||||
|
|
||||||
|
type internal OutputStreamId = | OutputStreamId of Guid
|
||||||
|
|
||||||
|
type private ThreadAwareWriter
|
||||||
|
(
|
||||||
|
local : AsyncLocal<OutputStreamId>,
|
||||||
|
underlying : Dictionary<OutputStreamId, TextWriter>,
|
||||||
|
mem : Dictionary<OutputStreamId, MemoryStream>
|
||||||
|
)
|
||||||
|
=
|
||||||
|
inherit TextWriter ()
|
||||||
|
override _.get_Encoding () = Encoding.Default
|
||||||
|
|
||||||
|
override this.Write (v : char) : unit =
|
||||||
|
use prev = ExecutionContext.Capture ()
|
||||||
|
|
||||||
|
(fun _ ->
|
||||||
|
(fun () ->
|
||||||
|
match underlying.TryGetValue local.Value with
|
||||||
|
| true, output -> output.Write v
|
||||||
|
| false, _ ->
|
||||||
|
let wanted =
|
||||||
|
underlying |> Seq.map (fun (KeyValue (a, b)) -> $"%O{a}") |> String.concat "\n"
|
||||||
|
|
||||||
|
failwith $"no such context: %O{local.Value}\nwanted:\n"
|
||||||
|
)
|
||||||
|
|> lock underlying
|
||||||
|
)
|
||||||
|
|> fun action -> ExecutionContext.Run (prev, action, ())
|
||||||
|
|
||||||
|
override this.WriteLine (v : string) : unit =
|
||||||
|
use prev = ExecutionContext.Capture ()
|
||||||
|
|
||||||
|
(fun _ ->
|
||||||
|
(fun () ->
|
||||||
|
match underlying.TryGetValue local.Value with
|
||||||
|
| true, output -> output.WriteLine v
|
||||||
|
| false, _ ->
|
||||||
|
let wanted =
|
||||||
|
underlying |> Seq.map (fun (KeyValue (a, b)) -> $"%O{a}") |> String.concat "\n"
|
||||||
|
|
||||||
|
failwith $"no such context: %O{local.Value}\nwanted:\n"
|
||||||
|
)
|
||||||
|
|> lock underlying
|
||||||
|
)
|
||||||
|
|> fun action -> ExecutionContext.Run (prev, action, ())
|
||||||
|
|
||||||
|
/// Wraps up the necessary context to intercept global state.
|
||||||
|
[<NoEquality ; NoComparison>]
|
||||||
|
type TestContexts =
|
||||||
|
private
|
||||||
|
{
|
||||||
|
/// Accesses to this must be locked on StdOutWriters.
|
||||||
|
StdOuts : Dictionary<OutputStreamId, MemoryStream>
|
||||||
|
/// Accesses to this must be locked on StdErrWriters.
|
||||||
|
StdErrs : Dictionary<OutputStreamId, MemoryStream>
|
||||||
|
StdOutWriters : Dictionary<OutputStreamId, TextWriter>
|
||||||
|
StdErrWriters : Dictionary<OutputStreamId, TextWriter>
|
||||||
|
StdOutWriter : TextWriter
|
||||||
|
StdErrWriter : TextWriter
|
||||||
|
AsyncLocal : AsyncLocal<OutputStreamId>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call this exactly once.
|
||||||
|
static member Empty () =
|
||||||
|
let stdouts = Dictionary ()
|
||||||
|
let stderrs = Dictionary ()
|
||||||
|
let stdoutWriters = Dictionary ()
|
||||||
|
let stderrWriters = Dictionary ()
|
||||||
|
let local = AsyncLocal ()
|
||||||
|
let stdoutWriter = new ThreadAwareWriter (local, stdoutWriters, stdouts)
|
||||||
|
let stderrWriter = new ThreadAwareWriter (local, stderrWriters, stderrs)
|
||||||
|
|
||||||
|
{
|
||||||
|
StdOuts = stdouts
|
||||||
|
StdErrs = stderrs
|
||||||
|
StdOutWriter = stdoutWriter
|
||||||
|
StdErrWriter = stderrWriter
|
||||||
|
StdOutWriters = stdoutWriters
|
||||||
|
StdErrWriters = stderrWriters
|
||||||
|
AsyncLocal = local
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An output stream which will identify the ExecutionContext it's being written to from,
|
||||||
|
/// and will separate that output into its own stream internally.
|
||||||
|
member this.Stdout : TextWriter = this.StdOutWriter
|
||||||
|
|
||||||
|
/// An output stream which will identify the ExecutionContext it's being written to from,
|
||||||
|
/// and will separate that output into its own stream internally.
|
||||||
|
member this.Stderr : TextWriter = this.StdErrWriter
|
||||||
|
|
||||||
|
member internal this.DumpStdout (id : OutputStreamId) : string =
|
||||||
|
lock
|
||||||
|
this.StdOutWriters
|
||||||
|
(fun () ->
|
||||||
|
this.StdOutWriters.[id].Flush ()
|
||||||
|
this.StdOuts.[id].ToArray ()
|
||||||
|
)
|
||||||
|
|> Encoding.Default.GetString
|
||||||
|
|
||||||
|
member internal this.DumpStderr (id : OutputStreamId) : string =
|
||||||
|
lock
|
||||||
|
this.StdErrWriters
|
||||||
|
(fun () ->
|
||||||
|
this.StdErrWriters.[id].Flush ()
|
||||||
|
this.StdErrs.[id].ToArray ()
|
||||||
|
)
|
||||||
|
|> Encoding.Default.GetString
|
||||||
|
|
||||||
|
member internal this.NewOutputs () =
|
||||||
|
let id = Guid.NewGuid () |> OutputStreamId
|
||||||
|
let msOut = new MemoryStream ()
|
||||||
|
let wrOut = new StreamWriter (msOut)
|
||||||
|
let msErr = new MemoryStream ()
|
||||||
|
let wrErr = new StreamWriter (msErr)
|
||||||
|
|
||||||
|
lock
|
||||||
|
this.StdOutWriters
|
||||||
|
(fun () ->
|
||||||
|
this.StdOutWriters.Add (id, wrOut)
|
||||||
|
this.StdOuts.Add (id, msOut)
|
||||||
|
)
|
||||||
|
|
||||||
|
lock
|
||||||
|
this.StdErrWriters
|
||||||
|
(fun () ->
|
||||||
|
this.StdErrWriters.Add (id, wrErr)
|
||||||
|
this.StdErrs.Add (id, msErr)
|
||||||
|
)
|
||||||
|
|
||||||
|
id
|
||||||
|
|
||||||
|
interface IDisposable with
|
||||||
|
member this.Dispose () =
|
||||||
|
// TODO: dispose the streams
|
||||||
|
()
|
||||||
|
|
||||||
|
/// A separate AssemblyLoadContext within which you can run the tests in the given DLL.
|
||||||
|
/// Supply places to find the .NET runtimes.
|
||||||
|
type LoadContext (dll : FileInfo, runtimes : DirectoryInfo list, contexts : TestContexts) =
|
||||||
|
inherit AssemblyLoadContext ()
|
||||||
|
|
||||||
|
/// Load the assembly with the given name into this assembly context.
|
||||||
|
/// This additionally monkey-patches System.Console: it performs SetOut and SetError on them
|
||||||
|
/// so that they redirect their outputs into the given `TestContexts`.
|
||||||
|
override this.Load (target : AssemblyName) : Assembly =
|
||||||
|
let path = Path.Combine (dll.Directory.FullName, $"%s{target.Name}.dll")
|
||||||
|
|
||||||
|
let assy =
|
||||||
|
if File.Exists path then
|
||||||
|
this.LoadFromAssemblyPath path
|
||||||
|
else
|
||||||
|
|
||||||
|
runtimes
|
||||||
|
|> List.tryPick (fun di ->
|
||||||
|
let path = Path.Combine (di.FullName, $"%s{target.Name}.dll")
|
||||||
|
|
||||||
|
if File.Exists path then
|
||||||
|
this.LoadFromAssemblyPath path |> Some
|
||||||
|
else
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|> Option.defaultValue null
|
||||||
|
|
||||||
|
if target.Name = "System.Console" then
|
||||||
|
if isNull assy then
|
||||||
|
failwith "could not monkey-patch System.Console"
|
||||||
|
else
|
||||||
|
let consoleType = assy.GetType "System.Console"
|
||||||
|
let setOut = consoleType.GetMethod "SetOut"
|
||||||
|
setOut.Invoke ((null : obj), [| contexts.Stdout |]) |> unbox<unit>
|
||||||
|
let setErr = consoleType.GetMethod "SetError"
|
||||||
|
setErr.Invoke ((null : obj), [| contexts.Stderr |]) |> unbox<unit>
|
||||||
|
|
||||||
|
assy
|
||||||
|
else
|
||||||
|
assy
|
263
WoofWare.NUnitTestRunner.Lib/CreateTrxReport.fs
Normal file
263
WoofWare.NUnitTestRunner.Lib/CreateTrxReport.fs
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
namespace WoofWare.NUnitTestRunner
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Reflection
|
||||||
|
|
||||||
|
/// Methods for constructing TRX reports.
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module BuildTrxReport =
|
||||||
|
|
||||||
|
/// Build a TRX report from the given results.
|
||||||
|
let build
|
||||||
|
(assy : Assembly)
|
||||||
|
(creationTime : DateTimeOffset)
|
||||||
|
(startTime : DateTimeOffset)
|
||||||
|
(results : FixtureRunResults list)
|
||||||
|
: TrxReport
|
||||||
|
=
|
||||||
|
let finishTime = DateTimeOffset.Now
|
||||||
|
let finishTimeHumanReadable = finishTime.ToString @"yyyy-MM-dd HH:mm:ss"
|
||||||
|
let nowMachine = finishTime.ToString @"yyyy-MM-dd_HH_mm_ss"
|
||||||
|
|
||||||
|
let testListId = Guid.NewGuid ()
|
||||||
|
|
||||||
|
let testDefinitions, testEntries =
|
||||||
|
results
|
||||||
|
|> List.collect (fun results -> results.IndividualTestRunMetadata)
|
||||||
|
|> List.map (fun (data, _) ->
|
||||||
|
let defn =
|
||||||
|
{
|
||||||
|
Name = data.TestName
|
||||||
|
Storage = assy.Location.ToLowerInvariant ()
|
||||||
|
Id = data.TestId
|
||||||
|
Execution =
|
||||||
|
{
|
||||||
|
Id = data.ExecutionId
|
||||||
|
}
|
||||||
|
TestMethod =
|
||||||
|
{
|
||||||
|
CodeBase = assy.Location
|
||||||
|
AdapterTypeName = Uri "executor://woofware/"
|
||||||
|
ClassName = data.ClassName
|
||||||
|
Name = data.TestName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let entry : TrxTestEntry =
|
||||||
|
{
|
||||||
|
TestListId = testListId
|
||||||
|
ExecutionId = data.ExecutionId
|
||||||
|
TestId = data.TestId
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
defn, entry
|
||||||
|
)
|
||||||
|
|> List.unzip
|
||||||
|
|
||||||
|
let hostname = Environment.MachineName
|
||||||
|
|
||||||
|
let settings =
|
||||||
|
{
|
||||||
|
Name = "default"
|
||||||
|
Id = Guid.NewGuid ()
|
||||||
|
Deployment =
|
||||||
|
{
|
||||||
|
RunDeploymentRoot = $"_%s{hostname}_%s{nowMachine}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let testList : TrxTestListEntry =
|
||||||
|
{
|
||||||
|
Id = testListId
|
||||||
|
Name = "All"
|
||||||
|
}
|
||||||
|
|
||||||
|
let counters =
|
||||||
|
(TrxCounters.Zero, results)
|
||||||
|
// TODO: this is woefully inefficient
|
||||||
|
||> List.fold (fun counters results ->
|
||||||
|
let counters =
|
||||||
|
(counters, results.Failed)
|
||||||
|
||> List.fold (fun counters (_, _) ->
|
||||||
|
// TODO: the counters can be more specific about the failure mode
|
||||||
|
counters.AddFailed ()
|
||||||
|
)
|
||||||
|
|
||||||
|
let counters =
|
||||||
|
(counters, results.OtherFailures)
|
||||||
|
||> List.fold (fun counters _ ->
|
||||||
|
// TODO: the counters can be more specific about the failure mode
|
||||||
|
counters.AddFailed ()
|
||||||
|
)
|
||||||
|
|
||||||
|
(counters, results.Success)
|
||||||
|
||> List.fold (fun counters (_, success, _) ->
|
||||||
|
match success with
|
||||||
|
| TestMemberSuccess.Ok -> counters.AddPassed ()
|
||||||
|
| TestMemberSuccess.Ignored _
|
||||||
|
| TestMemberSuccess.Explicit _ -> counters.AddNotExecuted ()
|
||||||
|
| TestMemberSuccess.Inconclusive _ -> counters.AddInconclusive ()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: I'm sure we can do better than this; there's a whole range of possible
|
||||||
|
// states!
|
||||||
|
let outcome =
|
||||||
|
if counters.Failed > 0u then
|
||||||
|
TrxOutcome.Failed
|
||||||
|
else
|
||||||
|
TrxOutcome.Completed
|
||||||
|
|
||||||
|
let resultSummary : TrxResultsSummary =
|
||||||
|
{
|
||||||
|
Outcome = outcome
|
||||||
|
Counters = counters
|
||||||
|
Output =
|
||||||
|
{
|
||||||
|
StdOut = None
|
||||||
|
StdErr = None
|
||||||
|
ErrorInfo = None
|
||||||
|
}
|
||||||
|
RunInfos =
|
||||||
|
[
|
||||||
|
// TODO: capture stdout
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
let times : TrxReportTimes =
|
||||||
|
{
|
||||||
|
Creation = creationTime
|
||||||
|
Queuing = startTime
|
||||||
|
Start = startTime
|
||||||
|
Finish = finishTime
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let magicGuid = Guid.Parse "13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b"
|
||||||
|
|
||||||
|
let results =
|
||||||
|
results
|
||||||
|
|> List.collect (fun results -> results.IndividualTestRunMetadata)
|
||||||
|
|> List.map (fun (i, cause) ->
|
||||||
|
let exc =
|
||||||
|
match cause with
|
||||||
|
| Choice2Of3 _ -> None
|
||||||
|
| Choice1Of3 (TestMemberFailure.Malformed reasons) ->
|
||||||
|
{
|
||||||
|
StackTrace = None
|
||||||
|
Message = reasons |> String.concat "\n" |> Some
|
||||||
|
}
|
||||||
|
|> Some
|
||||||
|
| Choice1Of3 (TestMemberFailure.Failed fail)
|
||||||
|
| Choice1Of3 (TestMemberFailure.Failed fail)
|
||||||
|
| Choice1Of3 (TestMemberFailure.Failed fail) ->
|
||||||
|
((None, None), fail)
|
||||||
|
||> List.fold (fun (stackTrace, message) tf ->
|
||||||
|
match tf with
|
||||||
|
| TestFailure.TestFailed (UserMethodFailure.Threw (_, exc))
|
||||||
|
| TestFailure.SetUpFailed (UserMethodFailure.Threw (_, exc))
|
||||||
|
| TestFailure.TearDownFailed (UserMethodFailure.Threw (_, exc)) ->
|
||||||
|
let stackTrace =
|
||||||
|
match stackTrace with
|
||||||
|
| None -> (exc : Exception).ToString ()
|
||||||
|
| Some s -> s
|
||||||
|
|
||||||
|
(Some stackTrace, message)
|
||||||
|
| TestFailure.TestFailed (UserMethodFailure.BadParameters (_, expected, actual))
|
||||||
|
| TestFailure.SetUpFailed (UserMethodFailure.BadParameters (_, expected, actual))
|
||||||
|
| TestFailure.TearDownFailed (UserMethodFailure.BadParameters (_, expected, actual)) ->
|
||||||
|
let newMessage =
|
||||||
|
$"had parameter count mismatch: expected %i{expected.Length}, actual %i{actual.Length}"
|
||||||
|
|
||||||
|
let message =
|
||||||
|
match message with
|
||||||
|
| None -> newMessage
|
||||||
|
| Some message -> $"%s{message}\n%s{newMessage}"
|
||||||
|
|
||||||
|
(stackTrace, Some message)
|
||||||
|
| TestFailure.TestFailed (UserMethodFailure.ReturnedNonUnit (_, ret))
|
||||||
|
| TestFailure.SetUpFailed (UserMethodFailure.ReturnedNonUnit (_, ret))
|
||||||
|
| TestFailure.TearDownFailed (UserMethodFailure.ReturnedNonUnit (_, ret)) ->
|
||||||
|
let newMessage = $"returned non-unit value %O{ret}"
|
||||||
|
|
||||||
|
let message =
|
||||||
|
match message with
|
||||||
|
| None -> newMessage
|
||||||
|
| Some message -> $"%s{message}\n%s{newMessage}"
|
||||||
|
|
||||||
|
(stackTrace, Some message)
|
||||||
|
)
|
||||||
|
|> fun (stackTrace, message) ->
|
||||||
|
{
|
||||||
|
StackTrace = stackTrace
|
||||||
|
Message = message
|
||||||
|
}
|
||||||
|
|> Some
|
||||||
|
| Choice3Of3 (UserMethodFailure.Threw (_, exc)) ->
|
||||||
|
{
|
||||||
|
StackTrace = (exc : Exception).ToString () |> Some
|
||||||
|
Message = None
|
||||||
|
}
|
||||||
|
|> Some
|
||||||
|
| Choice3Of3 (UserMethodFailure.BadParameters (_, expected, actual)) ->
|
||||||
|
{
|
||||||
|
StackTrace = None
|
||||||
|
Message =
|
||||||
|
$"parameter count mismatch, expected %i{expected.Length}, actual %i{actual.Length}"
|
||||||
|
|> Some
|
||||||
|
}
|
||||||
|
|> Some
|
||||||
|
| Choice3Of3 (UserMethodFailure.ReturnedNonUnit (_, ret)) ->
|
||||||
|
{
|
||||||
|
Message = $"returned non-unit value %O{ret}" |> Some
|
||||||
|
StackTrace = None
|
||||||
|
}
|
||||||
|
|> Some
|
||||||
|
|
||||||
|
let outcome =
|
||||||
|
match cause with
|
||||||
|
| Choice1Of3 _ -> TrxTestOutcome.Failed
|
||||||
|
| Choice2Of3 TestMemberSuccess.Ok -> TrxTestOutcome.Passed
|
||||||
|
| Choice2Of3 (TestMemberSuccess.Inconclusive _) -> TrxTestOutcome.Inconclusive
|
||||||
|
| Choice2Of3 (TestMemberSuccess.Ignored _)
|
||||||
|
| Choice2Of3 (TestMemberSuccess.Explicit _) -> TrxTestOutcome.NotExecuted
|
||||||
|
// TODO: we can totally do better here, more fine-grained classification
|
||||||
|
| Choice3Of3 _ -> TrxTestOutcome.Failed
|
||||||
|
|
||||||
|
{
|
||||||
|
ExecutionId = i.ExecutionId
|
||||||
|
TestId = i.TestId
|
||||||
|
TestName = i.TestName
|
||||||
|
ComputerName = i.ComputerName
|
||||||
|
Duration = i.End - i.Start
|
||||||
|
StartTime = i.Start
|
||||||
|
EndTime = i.End
|
||||||
|
TestType = magicGuid
|
||||||
|
Outcome = outcome
|
||||||
|
TestListId = testListId
|
||||||
|
RelativeResultsDirectory = i.ExecutionId.ToString () // for some reason
|
||||||
|
Output =
|
||||||
|
match i.StdOut, i.StdErr, exc with
|
||||||
|
| None, None, None -> None
|
||||||
|
| stdout, stderr, exc ->
|
||||||
|
Some
|
||||||
|
{
|
||||||
|
TrxOutput.StdOut = stdout
|
||||||
|
StdErr = stderr
|
||||||
|
ErrorInfo = exc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid ()
|
||||||
|
Name = $"@%s{hostname} %s{finishTimeHumanReadable}"
|
||||||
|
Times = times
|
||||||
|
Settings = settings
|
||||||
|
Results = results
|
||||||
|
TestDefinitions = testDefinitions
|
||||||
|
TestEntries = testEntries
|
||||||
|
TestLists = [ testList ]
|
||||||
|
ResultsSummary = resultSummary
|
||||||
|
}
|
@@ -61,6 +61,24 @@ type Parallelizable<'scope> =
|
|||||||
/// This test must always be run on its own.
|
/// This test must always be run on its own.
|
||||||
| No
|
| No
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module Parallelizable =
|
||||||
|
/// Functorial map.
|
||||||
|
let inline map<'a, 'b> ([<InlineIfLambda>] f : 'a -> 'b) (p : Parallelizable<'a>) : Parallelizable<'b> =
|
||||||
|
match p with
|
||||||
|
| Parallelizable.No -> Parallelizable.No
|
||||||
|
| Parallelizable.Yes a -> Parallelizable.Yes (f a)
|
||||||
|
|
||||||
|
/// Functorial bind.
|
||||||
|
let inline bind<'a, 'b>
|
||||||
|
([<InlineIfLambda>] f : 'a -> Parallelizable<'b>)
|
||||||
|
(p : Parallelizable<'a>)
|
||||||
|
: Parallelizable<'b>
|
||||||
|
=
|
||||||
|
match p with
|
||||||
|
| Parallelizable.No -> Parallelizable.No
|
||||||
|
| Parallelizable.Yes a -> f a
|
||||||
|
|
||||||
/// A single method or member which holds some tests. (Often such a member will represent only one test, but e.g.
|
/// A single method or member which holds some tests. (Often such a member will represent only one test, but e.g.
|
||||||
/// if it has [<TestCaseSource>] then it represents multiple tests.)
|
/// if it has [<TestCaseSource>] then it represents multiple tests.)
|
||||||
type SingleTestMethod =
|
type SingleTestMethod =
|
||||||
@@ -88,6 +106,7 @@ type SingleTestMethod =
|
|||||||
|
|
||||||
/// A test fixture (usually represented by the [<TestFixture>]` attribute), which may contain many tests,
|
/// A test fixture (usually represented by the [<TestFixture>]` attribute), which may contain many tests,
|
||||||
/// each of which may run many times.
|
/// each of which may run many times.
|
||||||
|
[<NoComparison>]
|
||||||
type TestFixture =
|
type TestFixture =
|
||||||
{
|
{
|
||||||
/// The assembly which contains this TestFixture, loaded into a separate context.
|
/// The assembly which contains this TestFixture, loaded into a separate context.
|
||||||
@@ -143,6 +162,8 @@ type UserMethodFailure =
|
|||||||
| ReturnedNonUnit of name : string * result : obj
|
| ReturnedNonUnit of name : string * result : obj
|
||||||
/// A method threw.
|
/// A method threw.
|
||||||
| Threw of name : string * exn
|
| Threw of name : string * exn
|
||||||
|
/// Parameter count mismatch.
|
||||||
|
| BadParameters of name : string * expected : Type[] * actual : obj[]
|
||||||
|
|
||||||
/// Human-readable representation of the user failure.
|
/// Human-readable representation of the user failure.
|
||||||
override this.ToString () =
|
override this.ToString () =
|
||||||
@@ -151,12 +172,22 @@ type UserMethodFailure =
|
|||||||
$"User-defined method '%s{method}' returned a non-unit: %O{ret}"
|
$"User-defined method '%s{method}' returned a non-unit: %O{ret}"
|
||||||
| UserMethodFailure.Threw (method, exc) ->
|
| UserMethodFailure.Threw (method, exc) ->
|
||||||
$"User-defined method '%s{method}' threw: %s{exc.Message}\n %s{exc.StackTrace}"
|
$"User-defined method '%s{method}' threw: %s{exc.Message}\n %s{exc.StackTrace}"
|
||||||
|
| UserMethodFailure.BadParameters (method, expected, actual) ->
|
||||||
|
let expectedStr = expected |> Seq.map (fun t -> t.Name) |> String.concat ", "
|
||||||
|
|
||||||
|
let actualStr =
|
||||||
|
actual
|
||||||
|
|> Seq.map (fun s -> if isNull s then "null" else s.ToString ())
|
||||||
|
|> String.concat ", "
|
||||||
|
|
||||||
|
$"User-defined method '%s{method}' had parameter count mismatch. Expected: (%s{expectedStr}) (%i{expected.Length} params). Actual: (%s{actualStr}) (%i{actual.Length} params)"
|
||||||
|
|
||||||
/// Name (not fully-qualified) of the method which failed.
|
/// Name (not fully-qualified) of the method which failed.
|
||||||
member this.Name =
|
member this.Name =
|
||||||
match this with
|
match this with
|
||||||
| UserMethodFailure.Threw (name, _)
|
| UserMethodFailure.Threw (name, _)
|
||||||
| UserMethodFailure.ReturnedNonUnit (name, _) -> name
|
| UserMethodFailure.ReturnedNonUnit (name, _) -> name
|
||||||
|
| UserMethodFailure.BadParameters (name, _, _) -> name
|
||||||
|
|
||||||
/// Represents the failure of a single run of one test. An error signalled this way is a user error: the unit under
|
/// Represents the failure of a single run of one test. An error signalled this way is a user error: the unit under
|
||||||
/// test has misbehaved.
|
/// test has misbehaved.
|
||||||
|
@@ -7,11 +7,7 @@ open WoofWare.DotnetRuntimeLocator
|
|||||||
/// Functions for locating .NET runtimes.
|
/// Functions for locating .NET runtimes.
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module DotnetRuntime =
|
module DotnetRuntime =
|
||||||
let private selectRuntime
|
let private selectRuntime (config : RuntimeOptions) (f : DotnetEnvironmentInfo) : DirectoryInfo list =
|
||||||
(config : RuntimeOptions)
|
|
||||||
(f : DotnetEnvironmentInfo)
|
|
||||||
: Choice<DotnetEnvironmentFrameworkInfo, DotnetEnvironmentSdkInfo> option
|
|
||||||
=
|
|
||||||
let rollForward =
|
let rollForward =
|
||||||
match Environment.GetEnvironmentVariable "DOTNET_ROLL_FORWARD" with
|
match Environment.GetEnvironmentVariable "DOTNET_ROLL_FORWARD" with
|
||||||
| null ->
|
| null ->
|
||||||
@@ -20,6 +16,14 @@ module DotnetRuntime =
|
|||||||
|> Option.defaultValue RollForward.Minor
|
|> Option.defaultValue RollForward.Minor
|
||||||
| s -> RollForward.Parse s
|
| s -> RollForward.Parse s
|
||||||
|
|
||||||
|
if
|
||||||
|
Option.isSome config.IncludedFramework
|
||||||
|
|| Option.isSome config.IncludedFrameworks
|
||||||
|
then
|
||||||
|
// No need for a framework that's anywhere other than the given DLL.
|
||||||
|
[]
|
||||||
|
else
|
||||||
|
|
||||||
let desiredVersions =
|
let desiredVersions =
|
||||||
match config.Framework with
|
match config.Framework with
|
||||||
| Some f -> [ Version f.Version, f.Name ]
|
| Some f -> [ Version f.Version, f.Name ]
|
||||||
@@ -66,15 +70,13 @@ module DotnetRuntime =
|
|||||||
|
|
||||||
name, data.Installed
|
name, data.Installed
|
||||||
)
|
)
|
||||||
// TODO: how do we select between many available frameworks?
|
|> Seq.toList
|
||||||
|> Seq.tryHead
|
|
||||||
|
|
||||||
match available with
|
// TODO: maybe we can ask the SDK if we don't have any runtimes.
|
||||||
| Some (_, f) -> Some (Choice1Of2 f)
|
// But we keep on trucking: maybe we're self-contained, and we'll actually find all the runtime next to the
|
||||||
| None ->
|
// DLL.
|
||||||
// TODO: maybe we can ask the SDK. But we keep on trucking: maybe we're self-contained,
|
available
|
||||||
// and we'll actually find all the runtime next to the DLL.
|
|> List.map (fun (_name, runtime) -> DirectoryInfo $"%s{runtime.Path}/%s{runtime.Version}")
|
||||||
None
|
|
||||||
| _ -> failwith "non-minor RollForward not supported yet; please shout if you want it"
|
| _ -> failwith "non-minor RollForward not supported yet; please shout if you want it"
|
||||||
|
|
||||||
/// Given an executable DLL, locate the .NET runtime that can best run it.
|
/// Given an executable DLL, locate the .NET runtime that can best run it.
|
||||||
@@ -96,9 +98,4 @@ module DotnetRuntime =
|
|||||||
|
|
||||||
let runtime = selectRuntime runtimeConfig availableRuntimes
|
let runtime = selectRuntime runtimeConfig availableRuntimes
|
||||||
|
|
||||||
match runtime with
|
dll.Directory :: runtime
|
||||||
| None ->
|
|
||||||
// Keep on trucking: let's be optimistic and hope that we're self-contained.
|
|
||||||
[ dll.Directory ]
|
|
||||||
| Some (Choice1Of2 runtime) -> [ dll.Directory ; DirectoryInfo $"%s{runtime.Path}/%s{runtime.Version}" ]
|
|
||||||
| Some (Choice2Of2 sdk) -> [ dll.Directory ; DirectoryInfo sdk.Path ]
|
|
||||||
|
@@ -2,7 +2,7 @@ namespace WoofWare.NUnitTestRunner
|
|||||||
|
|
||||||
open System
|
open System
|
||||||
open System.IO
|
open System.IO
|
||||||
open PrattParser
|
open WoofWare.PrattParser
|
||||||
|
|
||||||
// Documentation:
|
// Documentation:
|
||||||
// https://learn.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests?pivots=mstest
|
// https://learn.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests?pivots=mstest
|
||||||
|
422
WoofWare.NUnitTestRunner.Lib/ParallelQueue.fs
Normal file
422
WoofWare.NUnitTestRunner.Lib/ParallelQueue.fs
Normal file
@@ -0,0 +1,422 @@
|
|||||||
|
namespace WoofWare.NUnitTestRunner
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Threading
|
||||||
|
open System.Threading.Tasks
|
||||||
|
|
||||||
|
type private ThunkEvaluator<'ret> =
|
||||||
|
abstract Eval<'a> : (unit -> 'a) -> AsyncReplyChannel<'a> -> 'ret
|
||||||
|
|
||||||
|
type private ThunkCrate =
|
||||||
|
abstract Apply<'ret> : ThunkEvaluator<'ret> -> 'ret
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module private ThunkCrate =
|
||||||
|
let make<'a> (t : unit -> 'a) (rc : AsyncReplyChannel<'a>) : ThunkCrate =
|
||||||
|
{ new ThunkCrate with
|
||||||
|
member _.Apply e = e.Eval t rc
|
||||||
|
}
|
||||||
|
|
||||||
|
type private FakeUnit = FakeUnit
|
||||||
|
|
||||||
|
/// A handle to a running test fixture.
|
||||||
|
type TestFixtureRunningToken = private | TestFixtureRunningToken of TestFixture
|
||||||
|
|
||||||
|
/// A handle to a test fixture whose setup method has been called.
|
||||||
|
type TestFixtureSetupToken = private | TestFixtureSetupToken of TestFixture
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module private TestFixtureSetupToken =
|
||||||
|
let vouchNoSetupRequired (TestFixtureRunningToken tf) = TestFixtureSetupToken tf
|
||||||
|
|
||||||
|
/// A handle to a test fixture whose setup method has been called.
|
||||||
|
type TestFixtureTearDownToken = private | TestFixtureTearDownToken of TestFixture
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module private TestFixtureTearDownToken =
|
||||||
|
let vouchNoTearDownRequired (TestFixtureSetupToken tf) = TestFixtureTearDownToken tf
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
type private MailboxMessage =
|
||||||
|
| Quit of AsyncReplyChannel<unit>
|
||||||
|
/// Check current state, see if we need to start more tests, etc.
|
||||||
|
| Reconcile
|
||||||
|
| RunTest of within : TestFixture * Parallelizable<unit> option * test : ThunkCrate
|
||||||
|
| BeginTestFixture of TestFixture * AsyncReplyChannel<TestFixtureRunningToken>
|
||||||
|
| EndTestFixture of TestFixtureTearDownToken * AsyncReplyChannel<unit>
|
||||||
|
|
||||||
|
type private RunningFixture =
|
||||||
|
{
|
||||||
|
Fixture : TestFixture
|
||||||
|
RunningCanParallelize : bool
|
||||||
|
Running : Task list
|
||||||
|
Waiting : ((unit -> Task) * Parallelizable<unit> option) list
|
||||||
|
}
|
||||||
|
|
||||||
|
static member Make (f : TestFixture) =
|
||||||
|
{
|
||||||
|
Fixture = f
|
||||||
|
Running = []
|
||||||
|
RunningCanParallelize = true
|
||||||
|
Waiting = []
|
||||||
|
}
|
||||||
|
|
||||||
|
type private RunningState =
|
||||||
|
{
|
||||||
|
MaxParallelism : int
|
||||||
|
// TODO: make these efficiently look-up-able
|
||||||
|
CurrentlyRunning : RunningFixture list
|
||||||
|
Waiting : (TestFixture * AsyncReplyChannel<TestFixtureRunningToken>) list
|
||||||
|
}
|
||||||
|
|
||||||
|
member this.NewTest (tf : TestFixture) (par : Parallelizable<unit> option) (test : unit -> Task) =
|
||||||
|
{
|
||||||
|
MaxParallelism = this.MaxParallelism
|
||||||
|
Waiting = this.Waiting
|
||||||
|
CurrentlyRunning =
|
||||||
|
let found = ref 0
|
||||||
|
|
||||||
|
this.CurrentlyRunning
|
||||||
|
|> List.map (fun f ->
|
||||||
|
if Object.ReferenceEquals (f.Fixture, tf) then
|
||||||
|
Interlocked.Increment found |> ignore<int>
|
||||||
|
|
||||||
|
{ f with
|
||||||
|
Waiting = (test, par) :: f.Waiting
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f
|
||||||
|
)
|
||||||
|
|> fun l ->
|
||||||
|
match found.Value with
|
||||||
|
| 1 -> l
|
||||||
|
| 0 -> failwith $"Unexpectedly did not find the running test fixture '%s{tf.Name}' to add a test to"
|
||||||
|
| _ -> failwith $"Unexpectedly found the running test fixture '%s{tf.Name}' multiple times in list"
|
||||||
|
}
|
||||||
|
|
||||||
|
member this.CompleteFixture (tf : TestFixture) : RunningState =
|
||||||
|
let rec go (acc : RunningFixture list) (running : RunningFixture list) =
|
||||||
|
match running with
|
||||||
|
| [] -> failwith "Caller has somehow called EndTestFixture while we're not running that test fixture"
|
||||||
|
| runningFixture :: tail ->
|
||||||
|
if Object.ReferenceEquals (runningFixture.Fixture, tf) then
|
||||||
|
match runningFixture.Running, runningFixture.Waiting with
|
||||||
|
| [], [] -> acc @ tail
|
||||||
|
| r, [] ->
|
||||||
|
failwith $"Caller has called EndTestFixture while its tests are still running (%i{r.Length})"
|
||||||
|
| [], r ->
|
||||||
|
failwith $"Caller has called EndTestFixture while it has tests waiting to run (%i{r.Length})"
|
||||||
|
| r, s ->
|
||||||
|
failwith
|
||||||
|
$"Caller has called EndTestFixture while it has tests waiting to run (%i{s.Length}) and test running (%i{r.Length})"
|
||||||
|
else
|
||||||
|
go (runningFixture :: acc) tail
|
||||||
|
|
||||||
|
let currentlyRunning = go [] this.CurrentlyRunning
|
||||||
|
|
||||||
|
{
|
||||||
|
CurrentlyRunning = currentlyRunning
|
||||||
|
Waiting = this.Waiting
|
||||||
|
MaxParallelism = this.MaxParallelism
|
||||||
|
}
|
||||||
|
|
||||||
|
type private MailboxState =
|
||||||
|
| Idle
|
||||||
|
| Running of RunningState
|
||||||
|
|
||||||
|
/// Run some things in parallel.
|
||||||
|
/// TODO: actually implement the parallelism! Right now this just runs everything serially.
|
||||||
|
/// TODO: consume the cancellation token
|
||||||
|
type ParallelQueue
|
||||||
|
(parallelism : int option, _scope : Parallelizable<AssemblyParallelScope> option, ?ct : CancellationToken)
|
||||||
|
=
|
||||||
|
let parallelism =
|
||||||
|
match parallelism with
|
||||||
|
| None -> max (Environment.ProcessorCount / 2) 2
|
||||||
|
| Some p -> p
|
||||||
|
|
||||||
|
let rec processTask (state : MailboxState) (m : MailboxProcessor<MailboxMessage>) =
|
||||||
|
async {
|
||||||
|
let! message = m.Receive ()
|
||||||
|
|
||||||
|
match message with
|
||||||
|
| MailboxMessage.Quit rc -> rc.Reply ()
|
||||||
|
| MailboxMessage.Reconcile ->
|
||||||
|
match state with
|
||||||
|
| Idle -> return! processTask state m
|
||||||
|
| Running r ->
|
||||||
|
|
||||||
|
match r.CurrentlyRunning with
|
||||||
|
| [] ->
|
||||||
|
match r.Waiting with
|
||||||
|
| [] -> return! processTask Idle m
|
||||||
|
| (head, rc) :: tail ->
|
||||||
|
rc.Reply (TestFixtureRunningToken head)
|
||||||
|
|
||||||
|
let newRunning =
|
||||||
|
{
|
||||||
|
Fixture = head
|
||||||
|
Running = []
|
||||||
|
RunningCanParallelize = true
|
||||||
|
Waiting = []
|
||||||
|
}
|
||||||
|
|
||||||
|
let state =
|
||||||
|
{
|
||||||
|
MaxParallelism = r.MaxParallelism
|
||||||
|
CurrentlyRunning = [ newRunning ]
|
||||||
|
Waiting = tail
|
||||||
|
}
|
||||||
|
// For now, we'll just run one fixture at a time. When we run multiple fixtures in parallel,
|
||||||
|
// we probably want to call Reconcile here again.
|
||||||
|
return! processTask (Running state) m
|
||||||
|
| [ currentlyRunning ] ->
|
||||||
|
let currentlyRunningTasks =
|
||||||
|
currentlyRunning.Running |> List.filter (fun t -> not t.IsCompleted)
|
||||||
|
|
||||||
|
let r =
|
||||||
|
{ r with
|
||||||
|
CurrentlyRunning =
|
||||||
|
[
|
||||||
|
{ currentlyRunning with
|
||||||
|
Running = currentlyRunningTasks
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
match currentlyRunningTasks with
|
||||||
|
| [] ->
|
||||||
|
match currentlyRunning.Waiting with
|
||||||
|
| [] ->
|
||||||
|
// Nothing to run yet
|
||||||
|
return! processTask (Running r) m
|
||||||
|
| (head, par) :: tail ->
|
||||||
|
let par =
|
||||||
|
match par with
|
||||||
|
| None -> true
|
||||||
|
| Some Parallelizable.No -> false
|
||||||
|
| Some (Parallelizable.Yes ()) -> true
|
||||||
|
|
||||||
|
let state =
|
||||||
|
{
|
||||||
|
Fixture = currentlyRunning.Fixture
|
||||||
|
RunningCanParallelize = par
|
||||||
|
Waiting = tail
|
||||||
|
Running = [ head () ]
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Post MailboxMessage.Reconcile
|
||||||
|
|
||||||
|
return!
|
||||||
|
processTask
|
||||||
|
(Running
|
||||||
|
{ r with
|
||||||
|
CurrentlyRunning = [ state ]
|
||||||
|
})
|
||||||
|
m
|
||||||
|
|
||||||
|
| currentlyRunningTasks ->
|
||||||
|
|
||||||
|
if currentlyRunningTasks.Length >= parallelism then
|
||||||
|
return! processTask (Running r) m
|
||||||
|
else
|
||||||
|
|
||||||
|
match currentlyRunning.Waiting, currentlyRunning.RunningCanParallelize with
|
||||||
|
| [], _ ->
|
||||||
|
// No new candidates.
|
||||||
|
return! processTask (Running r) m
|
||||||
|
| _, false ->
|
||||||
|
// The running test(s) can't have others added.
|
||||||
|
return! processTask (Running r) m
|
||||||
|
| (head, par) :: tail, true ->
|
||||||
|
match par with
|
||||||
|
| Some Parallelizable.No -> return! processTask (Running r) m
|
||||||
|
| Some (Parallelizable.Yes ()) ->
|
||||||
|
let state =
|
||||||
|
{
|
||||||
|
RunningState.MaxParallelism = r.MaxParallelism
|
||||||
|
Waiting = r.Waiting
|
||||||
|
CurrentlyRunning =
|
||||||
|
[
|
||||||
|
{
|
||||||
|
Fixture = currentlyRunning.Fixture
|
||||||
|
RunningCanParallelize = true
|
||||||
|
Running = head () :: currentlyRunning.Running
|
||||||
|
Waiting = tail
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Post MailboxMessage.Reconcile
|
||||||
|
return! processTask (Running state) m
|
||||||
|
| None ->
|
||||||
|
match currentlyRunning.Fixture.Parallelize with
|
||||||
|
| Some Parallelizable.No
|
||||||
|
| Some (Parallelizable.Yes ClassParallelScope.Self)
|
||||||
|
| Some (Parallelizable.Yes ClassParallelScope.Fixtures) ->
|
||||||
|
// Can't add this test to the parallel queue right now
|
||||||
|
return! processTask (Running r) m
|
||||||
|
| None
|
||||||
|
| Some (Parallelizable.Yes ClassParallelScope.All)
|
||||||
|
| Some (Parallelizable.Yes ClassParallelScope.Children) ->
|
||||||
|
let state =
|
||||||
|
{
|
||||||
|
Fixture = currentlyRunning.Fixture
|
||||||
|
RunningCanParallelize = true
|
||||||
|
Waiting = tail
|
||||||
|
Running = (head ()) :: currentlyRunningTasks
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Post MailboxMessage.Reconcile
|
||||||
|
|
||||||
|
return!
|
||||||
|
processTask
|
||||||
|
(Running
|
||||||
|
{ r with
|
||||||
|
CurrentlyRunning = [ state ]
|
||||||
|
})
|
||||||
|
m
|
||||||
|
| _ -> failwith "Logic error: we currently only run one fixture at a time"
|
||||||
|
| MailboxMessage.BeginTestFixture (tf, rc) ->
|
||||||
|
match state with
|
||||||
|
| Running state ->
|
||||||
|
let state =
|
||||||
|
{
|
||||||
|
MaxParallelism = state.MaxParallelism
|
||||||
|
CurrentlyRunning = state.CurrentlyRunning
|
||||||
|
Waiting = (tf, rc) :: state.Waiting
|
||||||
|
}
|
||||||
|
|> Running
|
||||||
|
|
||||||
|
m.Post MailboxMessage.Reconcile
|
||||||
|
return! processTask state m
|
||||||
|
| Idle ->
|
||||||
|
let state =
|
||||||
|
{
|
||||||
|
MaxParallelism = parallelism
|
||||||
|
CurrentlyRunning = []
|
||||||
|
Waiting = [ (tf, rc) ]
|
||||||
|
}
|
||||||
|
|> Running
|
||||||
|
|
||||||
|
m.Post MailboxMessage.Reconcile
|
||||||
|
return! processTask state m
|
||||||
|
| MailboxMessage.EndTestFixture (TestFixtureTearDownToken tf, rc) ->
|
||||||
|
match state with
|
||||||
|
| Idle ->
|
||||||
|
return failwith "Caller has somehow called EndTestFixture while we're not running a test fixture"
|
||||||
|
| Running state ->
|
||||||
|
let state = state.CompleteFixture tf
|
||||||
|
rc.Reply ()
|
||||||
|
m.Post MailboxMessage.Reconcile
|
||||||
|
return! processTask (Running state) m
|
||||||
|
| MailboxMessage.RunTest (withinFixture, par, message) ->
|
||||||
|
let t () =
|
||||||
|
{ new ThunkEvaluator<_> with
|
||||||
|
member _.Eval<'b> (t : unit -> 'b) rc =
|
||||||
|
let tcs = TaskCompletionSource TaskCreationOptions.RunContinuationsAsynchronously
|
||||||
|
use ec = ExecutionContext.Capture ()
|
||||||
|
|
||||||
|
fun () ->
|
||||||
|
ExecutionContext.Run (
|
||||||
|
ec,
|
||||||
|
(fun _ ->
|
||||||
|
let result = t ()
|
||||||
|
tcs.SetResult ()
|
||||||
|
m.Post MailboxMessage.Reconcile
|
||||||
|
rc.Reply result
|
||||||
|
),
|
||||||
|
()
|
||||||
|
)
|
||||||
|
|> Task.Factory.StartNew
|
||||||
|
|> ignore<Task>
|
||||||
|
|
||||||
|
tcs.Task
|
||||||
|
}
|
||||||
|
|> message.Apply
|
||||||
|
|
||||||
|
let state =
|
||||||
|
match state with
|
||||||
|
| Idle -> failwith "somehow asked the queue to run tests when there is no active fixture"
|
||||||
|
| Running state -> state.NewTest withinFixture par t |> Running
|
||||||
|
|
||||||
|
m.Post MailboxMessage.Reconcile
|
||||||
|
|
||||||
|
return! processTask state m
|
||||||
|
}
|
||||||
|
|
||||||
|
let mb = new MailboxProcessor<_> (processTask MailboxState.Idle)
|
||||||
|
do mb.Start ()
|
||||||
|
|
||||||
|
/// Request to run the given action, freely in parallel with other running tests.
|
||||||
|
/// The resulting Task will return when the action has completed.
|
||||||
|
member _.Run<'a>
|
||||||
|
(TestFixtureSetupToken parent)
|
||||||
|
(scope : Parallelizable<unit> option)
|
||||||
|
(action : unit -> 'a)
|
||||||
|
: 'a Task
|
||||||
|
=
|
||||||
|
(fun rc -> MailboxMessage.RunTest (parent, scope, ThunkCrate.make action rc))
|
||||||
|
|> mb.PostAndAsyncReply
|
||||||
|
|> Async.StartAsTask
|
||||||
|
|
||||||
|
/// Declare that we wish to start the given test fixture. The resulting Task will return
|
||||||
|
/// when you are allowed to start running tests from that fixture.
|
||||||
|
/// Once you've finished running tests from that fixture, call EndTestFixture.
|
||||||
|
member _.StartTestFixture (tf : TestFixture) : Task<TestFixtureRunningToken> =
|
||||||
|
fun rc -> MailboxMessage.BeginTestFixture (tf, rc)
|
||||||
|
|> mb.PostAndAsyncReply
|
||||||
|
|> Async.StartAsTask
|
||||||
|
|
||||||
|
/// Run the given one-time setup for the test fixture.
|
||||||
|
member _.RunTestSetup (TestFixtureRunningToken parent) (action : unit -> 'a) : ('a * TestFixtureSetupToken) Task =
|
||||||
|
task {
|
||||||
|
let par =
|
||||||
|
parent.Parallelize
|
||||||
|
|> Option.map (fun p ->
|
||||||
|
match p with
|
||||||
|
| Parallelizable.No -> Parallelizable.No
|
||||||
|
| Parallelizable.Yes _ -> Parallelizable.Yes ()
|
||||||
|
)
|
||||||
|
|
||||||
|
let! response =
|
||||||
|
(fun rc -> MailboxMessage.RunTest (parent, par, ThunkCrate.make action rc))
|
||||||
|
|> mb.PostAndAsyncReply
|
||||||
|
|
||||||
|
return response, TestFixtureSetupToken parent
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run the given one-time tear-down for the test fixture.
|
||||||
|
member _.RunTestTearDown
|
||||||
|
(TestFixtureSetupToken parent)
|
||||||
|
(action : unit -> 'a)
|
||||||
|
: ('a * TestFixtureTearDownToken) Task
|
||||||
|
=
|
||||||
|
task {
|
||||||
|
let par =
|
||||||
|
parent.Parallelize
|
||||||
|
|> Option.map (fun p ->
|
||||||
|
match p with
|
||||||
|
| Parallelizable.No -> Parallelizable.No
|
||||||
|
| Parallelizable.Yes _ -> Parallelizable.Yes ()
|
||||||
|
)
|
||||||
|
|
||||||
|
let! response =
|
||||||
|
(fun rc -> MailboxMessage.RunTest (parent, par, ThunkCrate.make action rc))
|
||||||
|
|> mb.PostAndAsyncReply
|
||||||
|
|
||||||
|
return response, TestFixtureTearDownToken parent
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Declare that we have finished submitting requests to run in the given test fixture.
|
||||||
|
/// You don't need to worry about when the resulting Task returns, but we provide it just in case.
|
||||||
|
member _.EndTestFixture (tf : TestFixtureTearDownToken) : Task<unit> =
|
||||||
|
(fun rc -> MailboxMessage.EndTestFixture (tf, rc))
|
||||||
|
|> mb.PostAndAsyncReply
|
||||||
|
|> Async.StartAsTask
|
||||||
|
|
||||||
|
interface IDisposable with
|
||||||
|
member _.Dispose () =
|
||||||
|
// Still race conditions, of course: people could still be submitting after we finish the sync.
|
||||||
|
mb.PostAndReply MailboxMessage.Quit
|
||||||
|
(mb :> IDisposable).Dispose ()
|
29
WoofWare.NUnitTestRunner.Lib/ParallelScope.fs
Normal file
29
WoofWare.NUnitTestRunner.Lib/ParallelScope.fs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
namespace WoofWare.NUnitTestRunner
|
||||||
|
|
||||||
|
/// Our own strongly-typed rendering of the NUnit ParallelScope enum.
|
||||||
|
/// This is more tightly modelled by ClassParallelScope and AssemblyParallelScope in our own domain; this type exists
|
||||||
|
/// for the initial interop.
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
type ParallelScope =
|
||||||
|
/// Corresponds to NUnit's ParallelScope.Fixtures.
|
||||||
|
| Fixtures
|
||||||
|
/// Corresponds to NUnit's ParallelScope.Children.
|
||||||
|
| Children
|
||||||
|
/// Corresponds to NUnit's ParallelScope.All.
|
||||||
|
| All
|
||||||
|
/// Corresponds to NUnit's ParallelScope.Self.
|
||||||
|
| Self
|
||||||
|
/// Corresponds to NUnit's ParallelScope.None.
|
||||||
|
| None
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module ParallelScope =
|
||||||
|
/// Convert the weakly-typed C# enum that is NUnit's `ParallelScope` to a strongly-typed representation.
|
||||||
|
let ofInt (n : int) =
|
||||||
|
match n with
|
||||||
|
| 512 -> ParallelScope.Fixtures
|
||||||
|
| 256 -> ParallelScope.Children
|
||||||
|
| 257 -> ParallelScope.All
|
||||||
|
| 1 -> ParallelScope.Self
|
||||||
|
| 2 -> ParallelScope.None
|
||||||
|
| _ -> failwith $"Unrecognised ParallelScope enum: %i{n}"
|
@@ -16,6 +16,8 @@ type internal RuntimeOptions =
|
|||||||
Tfm : string
|
Tfm : string
|
||||||
Framework : FrameworkDescription option
|
Framework : FrameworkDescription option
|
||||||
Frameworks : FrameworkDescription list option
|
Frameworks : FrameworkDescription list option
|
||||||
|
IncludedFramework : FrameworkDescription option
|
||||||
|
IncludedFrameworks : FrameworkDescription list option
|
||||||
RollForward : string option
|
RollForward : string option
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -94,7 +94,27 @@ module SingleTestMethod =
|
|||||||
match par with
|
match par with
|
||||||
| Some _ -> failwith $"Got multiple parallelization attributes on %s{method.Name}"
|
| Some _ -> failwith $"Got multiple parallelization attributes on %s{method.Name}"
|
||||||
| None ->
|
| None ->
|
||||||
(remaining, isTest, sources, hasData, mods, cats, repeat, comb, Some (Parallelizable.Yes ()))
|
let arg =
|
||||||
|
match Seq.toList attr.ConstructorArguments with
|
||||||
|
| [] -> Parallelizable.Yes ()
|
||||||
|
| [ x ] ->
|
||||||
|
if x.ArgumentType.Name <> "ParallelScope" then
|
||||||
|
failwith
|
||||||
|
$"Got argument %O{x.Value} of unrecognised type %s{x.ArgumentType.Name} on [<Parallelizable>] attribute; expected ParallelScope"
|
||||||
|
|
||||||
|
match ParallelScope.ofInt (unbox<int> x.Value) with
|
||||||
|
| ParallelScope.Children ->
|
||||||
|
failwith
|
||||||
|
$"Unexpected ParallelScope.Children on test %s{method.Name}; this is not valid on individual tests"
|
||||||
|
| ParallelScope.Fixtures ->
|
||||||
|
failwith
|
||||||
|
$"Unexpected ParallelScope.Children on test %s{method.Name}; this is not valid on individual tests"
|
||||||
|
| ParallelScope.All
|
||||||
|
| ParallelScope.Self -> Parallelizable.Yes ()
|
||||||
|
| ParallelScope.None -> Parallelizable.No
|
||||||
|
| s -> failwith $"Got multiple arguments on a [<Parallelizable>] attribute: %O{s}"
|
||||||
|
|
||||||
|
(remaining, isTest, sources, hasData, mods, cats, repeat, comb, Some arg)
|
||||||
| s when s.StartsWith ("NUnit.Framework", StringComparison.Ordinal) ->
|
| s when s.StartsWith ("NUnit.Framework", StringComparison.Ordinal) ->
|
||||||
failwith $"Unrecognised attribute on function %s{method.Name}: %s{attr.AttributeType.FullName}"
|
failwith $"Unrecognised attribute on function %s{method.Name}: %s{attr.AttributeType.FullName}"
|
||||||
| _ -> (attr :: remaining, isTest, sources, hasData, mods, cats, repeat, comb, par)
|
| _ -> (attr :: remaining, isTest, sources, hasData, mods, cats, repeat, comb, par)
|
||||||
|
@@ -1,8 +1,34 @@
|
|||||||
|
WoofWare.NUnitTestRunner.Args inherit obj, implements WoofWare.NUnitTestRunner.Args System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
|
WoofWare.NUnitTestRunner.Args..ctor [constructor]: (System.IO.FileInfo, System.IO.FileInfo option, (string * WoofWare.NUnitTestRunner.Filter) option, WoofWare.NUnitTestRunner.LogLevel, int option, System.TimeSpan option)
|
||||||
|
WoofWare.NUnitTestRunner.Args.Dll [property]: [read-only] System.IO.FileInfo
|
||||||
|
WoofWare.NUnitTestRunner.Args.Equals [method]: (WoofWare.NUnitTestRunner.Args, System.Collections.IEqualityComparer) -> bool
|
||||||
|
WoofWare.NUnitTestRunner.Args.Filter [property]: [read-only] (string * WoofWare.NUnitTestRunner.Filter) option
|
||||||
|
WoofWare.NUnitTestRunner.Args.get_Dll [method]: unit -> System.IO.FileInfo
|
||||||
|
WoofWare.NUnitTestRunner.Args.get_Filter [method]: unit -> (string * WoofWare.NUnitTestRunner.Filter) option
|
||||||
|
WoofWare.NUnitTestRunner.Args.get_LevelOfParallelism [method]: unit -> int option
|
||||||
|
WoofWare.NUnitTestRunner.Args.get_Logging [method]: unit -> WoofWare.NUnitTestRunner.LogLevel
|
||||||
|
WoofWare.NUnitTestRunner.Args.get_Timeout [method]: unit -> System.TimeSpan option
|
||||||
|
WoofWare.NUnitTestRunner.Args.get_Trx [method]: unit -> System.IO.FileInfo option
|
||||||
|
WoofWare.NUnitTestRunner.Args.LevelOfParallelism [property]: [read-only] int option
|
||||||
|
WoofWare.NUnitTestRunner.Args.Logging [property]: [read-only] WoofWare.NUnitTestRunner.LogLevel
|
||||||
|
WoofWare.NUnitTestRunner.Args.Parse [static method]: string list -> WoofWare.NUnitTestRunner.Args
|
||||||
|
WoofWare.NUnitTestRunner.Args.Timeout [property]: [read-only] System.TimeSpan option
|
||||||
|
WoofWare.NUnitTestRunner.Args.Trx [property]: [read-only] System.IO.FileInfo option
|
||||||
|
WoofWare.NUnitTestRunner.AssemblyLevelAttributes inherit obj, implements WoofWare.NUnitTestRunner.AssemblyLevelAttributes System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.NUnitTestRunner.AssemblyLevelAttributes System.IComparable, System.IComparable, System.Collections.IStructuralComparable
|
||||||
|
WoofWare.NUnitTestRunner.AssemblyLevelAttributes..ctor [constructor]: (int option, WoofWare.NUnitTestRunner.AssemblyParallelScope WoofWare.NUnitTestRunner.Parallelizable option)
|
||||||
|
WoofWare.NUnitTestRunner.AssemblyLevelAttributes.Equals [method]: (WoofWare.NUnitTestRunner.AssemblyLevelAttributes, System.Collections.IEqualityComparer) -> bool
|
||||||
|
WoofWare.NUnitTestRunner.AssemblyLevelAttributes.get_Parallelism [method]: unit -> int option
|
||||||
|
WoofWare.NUnitTestRunner.AssemblyLevelAttributes.get_Parallelizable [method]: unit -> WoofWare.NUnitTestRunner.AssemblyParallelScope WoofWare.NUnitTestRunner.Parallelizable option
|
||||||
|
WoofWare.NUnitTestRunner.AssemblyLevelAttributes.Parallelism [property]: [read-only] int option
|
||||||
|
WoofWare.NUnitTestRunner.AssemblyLevelAttributes.Parallelizable [property]: [read-only] WoofWare.NUnitTestRunner.AssemblyParallelScope WoofWare.NUnitTestRunner.Parallelizable option
|
||||||
|
WoofWare.NUnitTestRunner.AssemblyLevelAttributesModule inherit obj
|
||||||
|
WoofWare.NUnitTestRunner.AssemblyLevelAttributesModule.get [static method]: System.Reflection.Assembly -> WoofWare.NUnitTestRunner.AssemblyLevelAttributes
|
||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope inherit obj, implements WoofWare.NUnitTestRunner.AssemblyParallelScope System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.NUnitTestRunner.AssemblyParallelScope System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases
|
WoofWare.NUnitTestRunner.AssemblyParallelScope inherit obj, implements WoofWare.NUnitTestRunner.AssemblyParallelScope System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.NUnitTestRunner.AssemblyParallelScope System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases
|
||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope+Tags inherit obj
|
WoofWare.NUnitTestRunner.AssemblyParallelScope+Tags inherit obj
|
||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope+Tags.Children [static field]: int = 0
|
WoofWare.NUnitTestRunner.AssemblyParallelScope+Tags.Children [static field]: int = 0
|
||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope+Tags.Fixtures [static field]: int = 1
|
WoofWare.NUnitTestRunner.AssemblyParallelScope+Tags.Fixtures [static field]: int = 1
|
||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope.Children [static property]: [read-only] WoofWare.NUnitTestRunner.AssemblyParallelScope
|
WoofWare.NUnitTestRunner.AssemblyParallelScope.Children [static property]: [read-only] WoofWare.NUnitTestRunner.AssemblyParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.AssemblyParallelScope.Equals [method]: (WoofWare.NUnitTestRunner.AssemblyParallelScope, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope.Fixtures [static property]: [read-only] WoofWare.NUnitTestRunner.AssemblyParallelScope
|
WoofWare.NUnitTestRunner.AssemblyParallelScope.Fixtures [static property]: [read-only] WoofWare.NUnitTestRunner.AssemblyParallelScope
|
||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope.get_Children [static method]: unit -> WoofWare.NUnitTestRunner.AssemblyParallelScope
|
WoofWare.NUnitTestRunner.AssemblyParallelScope.get_Children [static method]: unit -> WoofWare.NUnitTestRunner.AssemblyParallelScope
|
||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope.get_Fixtures [static method]: unit -> WoofWare.NUnitTestRunner.AssemblyParallelScope
|
WoofWare.NUnitTestRunner.AssemblyParallelScope.get_Fixtures [static method]: unit -> WoofWare.NUnitTestRunner.AssemblyParallelScope
|
||||||
@@ -12,6 +38,8 @@ WoofWare.NUnitTestRunner.AssemblyParallelScope.get_Tag [method]: unit -> int
|
|||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope.IsChildren [property]: [read-only] bool
|
WoofWare.NUnitTestRunner.AssemblyParallelScope.IsChildren [property]: [read-only] bool
|
||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope.IsFixtures [property]: [read-only] bool
|
WoofWare.NUnitTestRunner.AssemblyParallelScope.IsFixtures [property]: [read-only] bool
|
||||||
WoofWare.NUnitTestRunner.AssemblyParallelScope.Tag [property]: [read-only] int
|
WoofWare.NUnitTestRunner.AssemblyParallelScope.Tag [property]: [read-only] int
|
||||||
|
WoofWare.NUnitTestRunner.BuildTrxReport inherit obj
|
||||||
|
WoofWare.NUnitTestRunner.BuildTrxReport.build [static method]: System.Reflection.Assembly -> System.DateTimeOffset -> System.DateTimeOffset -> WoofWare.NUnitTestRunner.FixtureRunResults list -> WoofWare.NUnitTestRunner.TrxReport
|
||||||
WoofWare.NUnitTestRunner.ClassParallelScope inherit obj, implements WoofWare.NUnitTestRunner.ClassParallelScope System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.NUnitTestRunner.ClassParallelScope System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 4 cases
|
WoofWare.NUnitTestRunner.ClassParallelScope inherit obj, implements WoofWare.NUnitTestRunner.ClassParallelScope System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.NUnitTestRunner.ClassParallelScope System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 4 cases
|
||||||
WoofWare.NUnitTestRunner.ClassParallelScope+Tags inherit obj
|
WoofWare.NUnitTestRunner.ClassParallelScope+Tags inherit obj
|
||||||
WoofWare.NUnitTestRunner.ClassParallelScope+Tags.All [static field]: int = 3
|
WoofWare.NUnitTestRunner.ClassParallelScope+Tags.All [static field]: int = 3
|
||||||
@@ -20,6 +48,7 @@ WoofWare.NUnitTestRunner.ClassParallelScope+Tags.Fixtures [static field]: int =
|
|||||||
WoofWare.NUnitTestRunner.ClassParallelScope+Tags.Self [static field]: int = 0
|
WoofWare.NUnitTestRunner.ClassParallelScope+Tags.Self [static field]: int = 0
|
||||||
WoofWare.NUnitTestRunner.ClassParallelScope.All [static property]: [read-only] WoofWare.NUnitTestRunner.ClassParallelScope
|
WoofWare.NUnitTestRunner.ClassParallelScope.All [static property]: [read-only] WoofWare.NUnitTestRunner.ClassParallelScope
|
||||||
WoofWare.NUnitTestRunner.ClassParallelScope.Children [static property]: [read-only] WoofWare.NUnitTestRunner.ClassParallelScope
|
WoofWare.NUnitTestRunner.ClassParallelScope.Children [static property]: [read-only] WoofWare.NUnitTestRunner.ClassParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ClassParallelScope.Equals [method]: (WoofWare.NUnitTestRunner.ClassParallelScope, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.ClassParallelScope.Fixtures [static property]: [read-only] WoofWare.NUnitTestRunner.ClassParallelScope
|
WoofWare.NUnitTestRunner.ClassParallelScope.Fixtures [static property]: [read-only] WoofWare.NUnitTestRunner.ClassParallelScope
|
||||||
WoofWare.NUnitTestRunner.ClassParallelScope.get_All [static method]: unit -> WoofWare.NUnitTestRunner.ClassParallelScope
|
WoofWare.NUnitTestRunner.ClassParallelScope.get_All [static method]: unit -> WoofWare.NUnitTestRunner.ClassParallelScope
|
||||||
WoofWare.NUnitTestRunner.ClassParallelScope.get_Children [static method]: unit -> WoofWare.NUnitTestRunner.ClassParallelScope
|
WoofWare.NUnitTestRunner.ClassParallelScope.get_Children [static method]: unit -> WoofWare.NUnitTestRunner.ClassParallelScope
|
||||||
@@ -41,6 +70,7 @@ WoofWare.NUnitTestRunner.Combinatorial+Tags inherit obj
|
|||||||
WoofWare.NUnitTestRunner.Combinatorial+Tags.Combinatorial [static field]: int = 0
|
WoofWare.NUnitTestRunner.Combinatorial+Tags.Combinatorial [static field]: int = 0
|
||||||
WoofWare.NUnitTestRunner.Combinatorial+Tags.Sequential [static field]: int = 1
|
WoofWare.NUnitTestRunner.Combinatorial+Tags.Sequential [static field]: int = 1
|
||||||
WoofWare.NUnitTestRunner.Combinatorial.Combinatorial [static property]: [read-only] WoofWare.NUnitTestRunner.Combinatorial
|
WoofWare.NUnitTestRunner.Combinatorial.Combinatorial [static property]: [read-only] WoofWare.NUnitTestRunner.Combinatorial
|
||||||
|
WoofWare.NUnitTestRunner.Combinatorial.Equals [method]: (WoofWare.NUnitTestRunner.Combinatorial, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.Combinatorial.get_Combinatorial [static method]: unit -> WoofWare.NUnitTestRunner.Combinatorial
|
WoofWare.NUnitTestRunner.Combinatorial.get_Combinatorial [static method]: unit -> WoofWare.NUnitTestRunner.Combinatorial
|
||||||
WoofWare.NUnitTestRunner.Combinatorial.get_IsCombinatorial [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Combinatorial.get_IsCombinatorial [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.Combinatorial.get_IsSequential [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Combinatorial.get_IsSequential [method]: unit -> bool
|
||||||
@@ -82,6 +112,7 @@ WoofWare.NUnitTestRunner.Filter+Tags.TestCategory [static field]: int = 2
|
|||||||
WoofWare.NUnitTestRunner.Filter+TestCategory inherit WoofWare.NUnitTestRunner.Filter
|
WoofWare.NUnitTestRunner.Filter+TestCategory inherit WoofWare.NUnitTestRunner.Filter
|
||||||
WoofWare.NUnitTestRunner.Filter+TestCategory.get_Item [method]: unit -> WoofWare.NUnitTestRunner.Match
|
WoofWare.NUnitTestRunner.Filter+TestCategory.get_Item [method]: unit -> WoofWare.NUnitTestRunner.Match
|
||||||
WoofWare.NUnitTestRunner.Filter+TestCategory.Item [property]: [read-only] WoofWare.NUnitTestRunner.Match
|
WoofWare.NUnitTestRunner.Filter+TestCategory.Item [property]: [read-only] WoofWare.NUnitTestRunner.Match
|
||||||
|
WoofWare.NUnitTestRunner.Filter.Equals [method]: (WoofWare.NUnitTestRunner.Filter, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.Filter.get_IsAnd [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Filter.get_IsAnd [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.Filter.get_IsFullyQualifiedName [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Filter.get_IsFullyQualifiedName [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.Filter.get_IsName [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Filter.get_IsName [method]: unit -> bool
|
||||||
@@ -107,6 +138,7 @@ WoofWare.NUnitTestRunner.FilterModule.parse [static method]: string -> WoofWare.
|
|||||||
WoofWare.NUnitTestRunner.FilterModule.shouldRun [static method]: WoofWare.NUnitTestRunner.Filter -> (WoofWare.NUnitTestRunner.TestFixture -> WoofWare.NUnitTestRunner.SingleTestMethod -> bool)
|
WoofWare.NUnitTestRunner.FilterModule.shouldRun [static method]: WoofWare.NUnitTestRunner.Filter -> (WoofWare.NUnitTestRunner.TestFixture -> WoofWare.NUnitTestRunner.SingleTestMethod -> bool)
|
||||||
WoofWare.NUnitTestRunner.FixtureRunResults inherit obj, implements WoofWare.NUnitTestRunner.FixtureRunResults System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.FixtureRunResults inherit obj, implements WoofWare.NUnitTestRunner.FixtureRunResults System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.FixtureRunResults..ctor [constructor]: ((WoofWare.NUnitTestRunner.TestMemberFailure * WoofWare.NUnitTestRunner.IndividualTestRunMetadata) list, (WoofWare.NUnitTestRunner.SingleTestMethod * WoofWare.NUnitTestRunner.TestMemberSuccess * WoofWare.NUnitTestRunner.IndividualTestRunMetadata) list, (WoofWare.NUnitTestRunner.UserMethodFailure * WoofWare.NUnitTestRunner.IndividualTestRunMetadata) list)
|
WoofWare.NUnitTestRunner.FixtureRunResults..ctor [constructor]: ((WoofWare.NUnitTestRunner.TestMemberFailure * WoofWare.NUnitTestRunner.IndividualTestRunMetadata) list, (WoofWare.NUnitTestRunner.SingleTestMethod * WoofWare.NUnitTestRunner.TestMemberSuccess * WoofWare.NUnitTestRunner.IndividualTestRunMetadata) list, (WoofWare.NUnitTestRunner.UserMethodFailure * WoofWare.NUnitTestRunner.IndividualTestRunMetadata) list)
|
||||||
|
WoofWare.NUnitTestRunner.FixtureRunResults.Equals [method]: (WoofWare.NUnitTestRunner.FixtureRunResults, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.FixtureRunResults.Failed [property]: [read-only] (WoofWare.NUnitTestRunner.TestMemberFailure * WoofWare.NUnitTestRunner.IndividualTestRunMetadata) list
|
WoofWare.NUnitTestRunner.FixtureRunResults.Failed [property]: [read-only] (WoofWare.NUnitTestRunner.TestMemberFailure * WoofWare.NUnitTestRunner.IndividualTestRunMetadata) list
|
||||||
WoofWare.NUnitTestRunner.FixtureRunResults.get_Failed [method]: unit -> (WoofWare.NUnitTestRunner.TestMemberFailure * WoofWare.NUnitTestRunner.IndividualTestRunMetadata) list
|
WoofWare.NUnitTestRunner.FixtureRunResults.get_Failed [method]: unit -> (WoofWare.NUnitTestRunner.TestMemberFailure * WoofWare.NUnitTestRunner.IndividualTestRunMetadata) list
|
||||||
WoofWare.NUnitTestRunner.FixtureRunResults.get_IndividualTestRunMetadata [method]: unit -> (WoofWare.NUnitTestRunner.IndividualTestRunMetadata * Microsoft.FSharp.Core.FSharpChoice<WoofWare.NUnitTestRunner.TestMemberFailure, WoofWare.NUnitTestRunner.TestMemberSuccess, WoofWare.NUnitTestRunner.UserMethodFailure>) list
|
WoofWare.NUnitTestRunner.FixtureRunResults.get_IndividualTestRunMetadata [method]: unit -> (WoofWare.NUnitTestRunner.IndividualTestRunMetadata * Microsoft.FSharp.Core.FSharpChoice<WoofWare.NUnitTestRunner.TestMemberFailure, WoofWare.NUnitTestRunner.TestMemberSuccess, WoofWare.NUnitTestRunner.UserMethodFailure>) list
|
||||||
@@ -120,6 +152,7 @@ WoofWare.NUnitTestRunner.IndividualTestRunMetadata..ctor [constructor]: (System.
|
|||||||
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.ClassName [property]: [read-only] string
|
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.ClassName [property]: [read-only] string
|
||||||
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.ComputerName [property]: [read-only] string
|
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.ComputerName [property]: [read-only] string
|
||||||
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.End [property]: [read-only] System.DateTimeOffset
|
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.End [property]: [read-only] System.DateTimeOffset
|
||||||
|
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.Equals [method]: (WoofWare.NUnitTestRunner.IndividualTestRunMetadata, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.ExecutionId [property]: [read-only] System.Guid
|
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.ExecutionId [property]: [read-only] System.Guid
|
||||||
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.get_ClassName [method]: unit -> string
|
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.get_ClassName [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.get_ComputerName [method]: unit -> string
|
WoofWare.NUnitTestRunner.IndividualTestRunMetadata.get_ComputerName [method]: unit -> string
|
||||||
@@ -143,6 +176,23 @@ WoofWare.NUnitTestRunner.ITestProgress.OnTestFixtureStart [method]: string -> in
|
|||||||
WoofWare.NUnitTestRunner.ITestProgress.OnTestMemberFinished [method]: string -> unit
|
WoofWare.NUnitTestRunner.ITestProgress.OnTestMemberFinished [method]: string -> unit
|
||||||
WoofWare.NUnitTestRunner.ITestProgress.OnTestMemberSkipped [method]: string -> unit
|
WoofWare.NUnitTestRunner.ITestProgress.OnTestMemberSkipped [method]: string -> unit
|
||||||
WoofWare.NUnitTestRunner.ITestProgress.OnTestMemberStart [method]: string -> unit
|
WoofWare.NUnitTestRunner.ITestProgress.OnTestMemberStart [method]: string -> unit
|
||||||
|
WoofWare.NUnitTestRunner.LoadContext inherit System.Runtime.Loader.AssemblyLoadContext
|
||||||
|
WoofWare.NUnitTestRunner.LoadContext..ctor [constructor]: (System.IO.FileInfo, System.IO.DirectoryInfo list, WoofWare.NUnitTestRunner.TestContexts)
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel inherit obj, implements WoofWare.NUnitTestRunner.LogLevel System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.NUnitTestRunner.LogLevel System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel+Tags inherit obj
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel+Tags.Nothing [static field]: int = 0
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel+Tags.Verbose [static field]: int = 1
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.Equals [method]: (WoofWare.NUnitTestRunner.LogLevel, System.Collections.IEqualityComparer) -> bool
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.get_IsNothing [method]: unit -> bool
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.get_IsVerbose [method]: unit -> bool
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.get_Nothing [static method]: unit -> WoofWare.NUnitTestRunner.LogLevel
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.get_Tag [method]: unit -> int
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.get_Verbose [static method]: unit -> WoofWare.NUnitTestRunner.LogLevel
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.IsNothing [property]: [read-only] bool
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.IsVerbose [property]: [read-only] bool
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.Nothing [static property]: [read-only] WoofWare.NUnitTestRunner.LogLevel
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.Tag [property]: [read-only] int
|
||||||
|
WoofWare.NUnitTestRunner.LogLevel.Verbose [static property]: [read-only] WoofWare.NUnitTestRunner.LogLevel
|
||||||
WoofWare.NUnitTestRunner.Match inherit obj, implements WoofWare.NUnitTestRunner.Match System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.NUnitTestRunner.Match System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases
|
WoofWare.NUnitTestRunner.Match inherit obj, implements WoofWare.NUnitTestRunner.Match System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.NUnitTestRunner.Match System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases
|
||||||
WoofWare.NUnitTestRunner.Match+Contains inherit WoofWare.NUnitTestRunner.Match
|
WoofWare.NUnitTestRunner.Match+Contains inherit WoofWare.NUnitTestRunner.Match
|
||||||
WoofWare.NUnitTestRunner.Match+Contains.get_Item [method]: unit -> string
|
WoofWare.NUnitTestRunner.Match+Contains.get_Item [method]: unit -> string
|
||||||
@@ -153,6 +203,7 @@ WoofWare.NUnitTestRunner.Match+Exact.Item [property]: [read-only] string
|
|||||||
WoofWare.NUnitTestRunner.Match+Tags inherit obj
|
WoofWare.NUnitTestRunner.Match+Tags inherit obj
|
||||||
WoofWare.NUnitTestRunner.Match+Tags.Contains [static field]: int = 1
|
WoofWare.NUnitTestRunner.Match+Tags.Contains [static field]: int = 1
|
||||||
WoofWare.NUnitTestRunner.Match+Tags.Exact [static field]: int = 0
|
WoofWare.NUnitTestRunner.Match+Tags.Exact [static field]: int = 0
|
||||||
|
WoofWare.NUnitTestRunner.Match.Equals [method]: (WoofWare.NUnitTestRunner.Match, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.Match.get_IsContains [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Match.get_IsContains [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.Match.get_IsExact [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Match.get_IsExact [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.Match.get_Tag [method]: unit -> int
|
WoofWare.NUnitTestRunner.Match.get_Tag [method]: unit -> int
|
||||||
@@ -171,6 +222,7 @@ WoofWare.NUnitTestRunner.Modifier+Ignored.reason [property]: [read-only] string
|
|||||||
WoofWare.NUnitTestRunner.Modifier+Tags inherit obj
|
WoofWare.NUnitTestRunner.Modifier+Tags inherit obj
|
||||||
WoofWare.NUnitTestRunner.Modifier+Tags.Explicit [static field]: int = 0
|
WoofWare.NUnitTestRunner.Modifier+Tags.Explicit [static field]: int = 0
|
||||||
WoofWare.NUnitTestRunner.Modifier+Tags.Ignored [static field]: int = 1
|
WoofWare.NUnitTestRunner.Modifier+Tags.Ignored [static field]: int = 1
|
||||||
|
WoofWare.NUnitTestRunner.Modifier.Equals [method]: (WoofWare.NUnitTestRunner.Modifier, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.Modifier.get_IsExplicit [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Modifier.get_IsExplicit [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.Modifier.get_IsIgnored [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Modifier.get_IsIgnored [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.Modifier.get_Tag [method]: unit -> int
|
WoofWare.NUnitTestRunner.Modifier.get_Tag [method]: unit -> int
|
||||||
@@ -179,6 +231,9 @@ WoofWare.NUnitTestRunner.Modifier.IsIgnored [property]: [read-only] bool
|
|||||||
WoofWare.NUnitTestRunner.Modifier.NewExplicit [static method]: string option -> WoofWare.NUnitTestRunner.Modifier
|
WoofWare.NUnitTestRunner.Modifier.NewExplicit [static method]: string option -> WoofWare.NUnitTestRunner.Modifier
|
||||||
WoofWare.NUnitTestRunner.Modifier.NewIgnored [static method]: string option -> WoofWare.NUnitTestRunner.Modifier
|
WoofWare.NUnitTestRunner.Modifier.NewIgnored [static method]: string option -> WoofWare.NUnitTestRunner.Modifier
|
||||||
WoofWare.NUnitTestRunner.Modifier.Tag [property]: [read-only] int
|
WoofWare.NUnitTestRunner.Modifier.Tag [property]: [read-only] int
|
||||||
|
WoofWare.NUnitTestRunner.Parallelizable inherit obj
|
||||||
|
WoofWare.NUnitTestRunner.Parallelizable.bind [static method]: ('a -> 'b WoofWare.NUnitTestRunner.Parallelizable) -> 'a WoofWare.NUnitTestRunner.Parallelizable -> 'b WoofWare.NUnitTestRunner.Parallelizable
|
||||||
|
WoofWare.NUnitTestRunner.Parallelizable.map [static method]: ('a -> 'b) -> 'a WoofWare.NUnitTestRunner.Parallelizable -> 'b WoofWare.NUnitTestRunner.Parallelizable
|
||||||
WoofWare.NUnitTestRunner.Parallelizable`1 inherit obj, implements 'scope WoofWare.NUnitTestRunner.Parallelizable System.IEquatable, System.Collections.IStructuralEquatable, 'scope WoofWare.NUnitTestRunner.Parallelizable System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases
|
WoofWare.NUnitTestRunner.Parallelizable`1 inherit obj, implements 'scope WoofWare.NUnitTestRunner.Parallelizable System.IEquatable, System.Collections.IStructuralEquatable, 'scope WoofWare.NUnitTestRunner.Parallelizable System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 2 cases
|
||||||
WoofWare.NUnitTestRunner.Parallelizable`1+Tags inherit obj
|
WoofWare.NUnitTestRunner.Parallelizable`1+Tags inherit obj
|
||||||
WoofWare.NUnitTestRunner.Parallelizable`1+Tags.No [static field]: int = 1
|
WoofWare.NUnitTestRunner.Parallelizable`1+Tags.No [static field]: int = 1
|
||||||
@@ -186,6 +241,7 @@ WoofWare.NUnitTestRunner.Parallelizable`1+Tags.Yes [static field]: int = 0
|
|||||||
WoofWare.NUnitTestRunner.Parallelizable`1+Yes inherit 'scope WoofWare.NUnitTestRunner.Parallelizable
|
WoofWare.NUnitTestRunner.Parallelizable`1+Yes inherit 'scope WoofWare.NUnitTestRunner.Parallelizable
|
||||||
WoofWare.NUnitTestRunner.Parallelizable`1+Yes.get_Item [method]: unit -> 'scope
|
WoofWare.NUnitTestRunner.Parallelizable`1+Yes.get_Item [method]: unit -> 'scope
|
||||||
WoofWare.NUnitTestRunner.Parallelizable`1+Yes.Item [property]: [read-only] 'scope
|
WoofWare.NUnitTestRunner.Parallelizable`1+Yes.Item [property]: [read-only] 'scope
|
||||||
|
WoofWare.NUnitTestRunner.Parallelizable`1.Equals [method]: ('scope WoofWare.NUnitTestRunner.Parallelizable, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.Parallelizable`1.get_IsNo [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Parallelizable`1.get_IsNo [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.Parallelizable`1.get_IsYes [method]: unit -> bool
|
WoofWare.NUnitTestRunner.Parallelizable`1.get_IsYes [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.Parallelizable`1.get_No [static method]: unit -> 'scope WoofWare.NUnitTestRunner.Parallelizable
|
WoofWare.NUnitTestRunner.Parallelizable`1.get_No [static method]: unit -> 'scope WoofWare.NUnitTestRunner.Parallelizable
|
||||||
@@ -195,10 +251,50 @@ WoofWare.NUnitTestRunner.Parallelizable`1.IsYes [property]: [read-only] bool
|
|||||||
WoofWare.NUnitTestRunner.Parallelizable`1.NewYes [static method]: 'scope -> 'scope WoofWare.NUnitTestRunner.Parallelizable
|
WoofWare.NUnitTestRunner.Parallelizable`1.NewYes [static method]: 'scope -> 'scope WoofWare.NUnitTestRunner.Parallelizable
|
||||||
WoofWare.NUnitTestRunner.Parallelizable`1.No [static property]: [read-only] 'scope WoofWare.NUnitTestRunner.Parallelizable
|
WoofWare.NUnitTestRunner.Parallelizable`1.No [static property]: [read-only] 'scope WoofWare.NUnitTestRunner.Parallelizable
|
||||||
WoofWare.NUnitTestRunner.Parallelizable`1.Tag [property]: [read-only] int
|
WoofWare.NUnitTestRunner.Parallelizable`1.Tag [property]: [read-only] int
|
||||||
|
WoofWare.NUnitTestRunner.ParallelQueue inherit obj, implements IDisposable
|
||||||
|
WoofWare.NUnitTestRunner.ParallelQueue..ctor [constructor]: (int option, WoofWare.NUnitTestRunner.AssemblyParallelScope WoofWare.NUnitTestRunner.Parallelizable option, System.Threading.CancellationToken option)
|
||||||
|
WoofWare.NUnitTestRunner.ParallelQueue.EndTestFixture [method]: WoofWare.NUnitTestRunner.TestFixtureTearDownToken -> unit System.Threading.Tasks.Task
|
||||||
|
WoofWare.NUnitTestRunner.ParallelQueue.Run [method]: WoofWare.NUnitTestRunner.TestFixtureSetupToken -> unit WoofWare.NUnitTestRunner.Parallelizable option -> (unit -> 'a) -> 'a System.Threading.Tasks.Task
|
||||||
|
WoofWare.NUnitTestRunner.ParallelQueue.RunTestSetup [method]: WoofWare.NUnitTestRunner.TestFixtureRunningToken -> (unit -> 'a) -> ('a * WoofWare.NUnitTestRunner.TestFixtureSetupToken) System.Threading.Tasks.Task
|
||||||
|
WoofWare.NUnitTestRunner.ParallelQueue.RunTestTearDown [method]: WoofWare.NUnitTestRunner.TestFixtureSetupToken -> (unit -> 'a) -> ('a * WoofWare.NUnitTestRunner.TestFixtureTearDownToken) System.Threading.Tasks.Task
|
||||||
|
WoofWare.NUnitTestRunner.ParallelQueue.StartTestFixture [method]: WoofWare.NUnitTestRunner.TestFixture -> WoofWare.NUnitTestRunner.TestFixtureRunningToken System.Threading.Tasks.Task
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope inherit obj, implements WoofWare.NUnitTestRunner.ParallelScope System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.NUnitTestRunner.ParallelScope System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 5 cases
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope+Tags inherit obj
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope+Tags.All [static field]: int = 2
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope+Tags.Children [static field]: int = 1
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope+Tags.Fixtures [static field]: int = 0
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope+Tags.None [static field]: int = 4
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope+Tags.Self [static field]: int = 3
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.All [static property]: [read-only] WoofWare.NUnitTestRunner.ParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.Children [static property]: [read-only] WoofWare.NUnitTestRunner.ParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.Equals [method]: (WoofWare.NUnitTestRunner.ParallelScope, System.Collections.IEqualityComparer) -> bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.Fixtures [static property]: [read-only] WoofWare.NUnitTestRunner.ParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_All [static method]: unit -> WoofWare.NUnitTestRunner.ParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_Children [static method]: unit -> WoofWare.NUnitTestRunner.ParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_Fixtures [static method]: unit -> WoofWare.NUnitTestRunner.ParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_IsAll [method]: unit -> bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_IsChildren [method]: unit -> bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_IsFixtures [method]: unit -> bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_IsNone [method]: unit -> bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_IsSelf [method]: unit -> bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_None [static method]: unit -> WoofWare.NUnitTestRunner.ParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_Self [static method]: unit -> WoofWare.NUnitTestRunner.ParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.get_Tag [method]: unit -> int
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.IsAll [property]: [read-only] bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.IsChildren [property]: [read-only] bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.IsFixtures [property]: [read-only] bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.IsNone [property]: [read-only] bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.IsSelf [property]: [read-only] bool
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.None [static property]: [read-only] WoofWare.NUnitTestRunner.ParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.Self [static property]: [read-only] WoofWare.NUnitTestRunner.ParallelScope
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScope.Tag [property]: [read-only] int
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScopeModule inherit obj
|
||||||
|
WoofWare.NUnitTestRunner.ParallelScopeModule.ofInt [static method]: int -> WoofWare.NUnitTestRunner.ParallelScope
|
||||||
WoofWare.NUnitTestRunner.SingleTestMethod inherit obj, implements WoofWare.NUnitTestRunner.SingleTestMethod System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.SingleTestMethod inherit obj, implements WoofWare.NUnitTestRunner.SingleTestMethod System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.SingleTestMethod..ctor [constructor]: (System.Reflection.MethodInfo, WoofWare.NUnitTestRunner.TestKind, WoofWare.NUnitTestRunner.Modifier list, string list, int option, WoofWare.NUnitTestRunner.Combinatorial option, unit WoofWare.NUnitTestRunner.Parallelizable option)
|
WoofWare.NUnitTestRunner.SingleTestMethod..ctor [constructor]: (System.Reflection.MethodInfo, WoofWare.NUnitTestRunner.TestKind, WoofWare.NUnitTestRunner.Modifier list, string list, int option, WoofWare.NUnitTestRunner.Combinatorial option, unit WoofWare.NUnitTestRunner.Parallelizable option)
|
||||||
WoofWare.NUnitTestRunner.SingleTestMethod.Categories [property]: [read-only] string list
|
WoofWare.NUnitTestRunner.SingleTestMethod.Categories [property]: [read-only] string list
|
||||||
WoofWare.NUnitTestRunner.SingleTestMethod.Combinatorial [property]: [read-only] WoofWare.NUnitTestRunner.Combinatorial option
|
WoofWare.NUnitTestRunner.SingleTestMethod.Combinatorial [property]: [read-only] WoofWare.NUnitTestRunner.Combinatorial option
|
||||||
|
WoofWare.NUnitTestRunner.SingleTestMethod.Equals [method]: (WoofWare.NUnitTestRunner.SingleTestMethod, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.SingleTestMethod.get_Categories [method]: unit -> string list
|
WoofWare.NUnitTestRunner.SingleTestMethod.get_Categories [method]: unit -> string list
|
||||||
WoofWare.NUnitTestRunner.SingleTestMethod.get_Combinatorial [method]: unit -> WoofWare.NUnitTestRunner.Combinatorial option
|
WoofWare.NUnitTestRunner.SingleTestMethod.get_Combinatorial [method]: unit -> WoofWare.NUnitTestRunner.Combinatorial option
|
||||||
WoofWare.NUnitTestRunner.SingleTestMethod.get_Kind [method]: unit -> WoofWare.NUnitTestRunner.TestKind
|
WoofWare.NUnitTestRunner.SingleTestMethod.get_Kind [method]: unit -> WoofWare.NUnitTestRunner.TestKind
|
||||||
@@ -215,6 +311,12 @@ WoofWare.NUnitTestRunner.SingleTestMethod.Parallelize [property]: [read-only] un
|
|||||||
WoofWare.NUnitTestRunner.SingleTestMethod.Repeat [property]: [read-only] int option
|
WoofWare.NUnitTestRunner.SingleTestMethod.Repeat [property]: [read-only] int option
|
||||||
WoofWare.NUnitTestRunner.SingleTestMethodModule inherit obj
|
WoofWare.NUnitTestRunner.SingleTestMethodModule inherit obj
|
||||||
WoofWare.NUnitTestRunner.SingleTestMethodModule.parse [static method]: string list -> System.Reflection.MethodInfo -> System.Reflection.CustomAttributeData list -> (WoofWare.NUnitTestRunner.SingleTestMethod option * System.Reflection.CustomAttributeData list)
|
WoofWare.NUnitTestRunner.SingleTestMethodModule.parse [static method]: string list -> System.Reflection.MethodInfo -> System.Reflection.CustomAttributeData list -> (WoofWare.NUnitTestRunner.SingleTestMethod option * System.Reflection.CustomAttributeData list)
|
||||||
|
WoofWare.NUnitTestRunner.TestContexts inherit obj, implements IDisposable
|
||||||
|
WoofWare.NUnitTestRunner.TestContexts.Empty [static method]: unit -> WoofWare.NUnitTestRunner.TestContexts
|
||||||
|
WoofWare.NUnitTestRunner.TestContexts.get_Stderr [method]: unit -> System.IO.TextWriter
|
||||||
|
WoofWare.NUnitTestRunner.TestContexts.get_Stdout [method]: unit -> System.IO.TextWriter
|
||||||
|
WoofWare.NUnitTestRunner.TestContexts.Stderr [property]: [read-only] System.IO.TextWriter
|
||||||
|
WoofWare.NUnitTestRunner.TestContexts.Stdout [property]: [read-only] System.IO.TextWriter
|
||||||
WoofWare.NUnitTestRunner.TestFailure inherit obj, implements WoofWare.NUnitTestRunner.TestFailure System.IEquatable, System.Collections.IStructuralEquatable - union type with 3 cases
|
WoofWare.NUnitTestRunner.TestFailure inherit obj, implements WoofWare.NUnitTestRunner.TestFailure System.IEquatable, System.Collections.IStructuralEquatable - union type with 3 cases
|
||||||
WoofWare.NUnitTestRunner.TestFailure+SetUpFailed inherit WoofWare.NUnitTestRunner.TestFailure
|
WoofWare.NUnitTestRunner.TestFailure+SetUpFailed inherit WoofWare.NUnitTestRunner.TestFailure
|
||||||
WoofWare.NUnitTestRunner.TestFailure+SetUpFailed.get_Item [method]: unit -> WoofWare.NUnitTestRunner.UserMethodFailure
|
WoofWare.NUnitTestRunner.TestFailure+SetUpFailed.get_Item [method]: unit -> WoofWare.NUnitTestRunner.UserMethodFailure
|
||||||
@@ -229,6 +331,7 @@ WoofWare.NUnitTestRunner.TestFailure+TearDownFailed.Item [property]: [read-only]
|
|||||||
WoofWare.NUnitTestRunner.TestFailure+TestFailed inherit WoofWare.NUnitTestRunner.TestFailure
|
WoofWare.NUnitTestRunner.TestFailure+TestFailed inherit WoofWare.NUnitTestRunner.TestFailure
|
||||||
WoofWare.NUnitTestRunner.TestFailure+TestFailed.get_Item [method]: unit -> WoofWare.NUnitTestRunner.UserMethodFailure
|
WoofWare.NUnitTestRunner.TestFailure+TestFailed.get_Item [method]: unit -> WoofWare.NUnitTestRunner.UserMethodFailure
|
||||||
WoofWare.NUnitTestRunner.TestFailure+TestFailed.Item [property]: [read-only] WoofWare.NUnitTestRunner.UserMethodFailure
|
WoofWare.NUnitTestRunner.TestFailure+TestFailed.Item [property]: [read-only] WoofWare.NUnitTestRunner.UserMethodFailure
|
||||||
|
WoofWare.NUnitTestRunner.TestFailure.Equals [method]: (WoofWare.NUnitTestRunner.TestFailure, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TestFailure.get_IsSetUpFailed [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestFailure.get_IsSetUpFailed [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.TestFailure.get_IsTearDownFailed [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestFailure.get_IsTearDownFailed [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.TestFailure.get_IsTestFailed [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestFailure.get_IsTestFailed [method]: unit -> bool
|
||||||
@@ -246,6 +349,7 @@ WoofWare.NUnitTestRunner.TestFixture inherit obj, implements WoofWare.NUnitTestR
|
|||||||
WoofWare.NUnitTestRunner.TestFixture..ctor [constructor]: (System.Reflection.Assembly, string, System.Type, System.Reflection.MethodInfo option, System.Reflection.MethodInfo option, System.Reflection.MethodInfo list, System.Reflection.MethodInfo list, obj list list, WoofWare.NUnitTestRunner.SingleTestMethod list, WoofWare.NUnitTestRunner.ClassParallelScope WoofWare.NUnitTestRunner.Parallelizable option)
|
WoofWare.NUnitTestRunner.TestFixture..ctor [constructor]: (System.Reflection.Assembly, string, System.Type, System.Reflection.MethodInfo option, System.Reflection.MethodInfo option, System.Reflection.MethodInfo list, System.Reflection.MethodInfo list, obj list list, WoofWare.NUnitTestRunner.SingleTestMethod list, WoofWare.NUnitTestRunner.ClassParallelScope WoofWare.NUnitTestRunner.Parallelizable option)
|
||||||
WoofWare.NUnitTestRunner.TestFixture.ContainingAssembly [property]: [read-only] System.Reflection.Assembly
|
WoofWare.NUnitTestRunner.TestFixture.ContainingAssembly [property]: [read-only] System.Reflection.Assembly
|
||||||
WoofWare.NUnitTestRunner.TestFixture.Empty [static method]: System.Type -> WoofWare.NUnitTestRunner.ClassParallelScope WoofWare.NUnitTestRunner.Parallelizable option -> obj list list -> WoofWare.NUnitTestRunner.TestFixture
|
WoofWare.NUnitTestRunner.TestFixture.Empty [static method]: System.Type -> WoofWare.NUnitTestRunner.ClassParallelScope WoofWare.NUnitTestRunner.Parallelizable option -> obj list list -> WoofWare.NUnitTestRunner.TestFixture
|
||||||
|
WoofWare.NUnitTestRunner.TestFixture.Equals [method]: (WoofWare.NUnitTestRunner.TestFixture, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TestFixture.get_ContainingAssembly [method]: unit -> System.Reflection.Assembly
|
WoofWare.NUnitTestRunner.TestFixture.get_ContainingAssembly [method]: unit -> System.Reflection.Assembly
|
||||||
WoofWare.NUnitTestRunner.TestFixture.get_Name [method]: unit -> string
|
WoofWare.NUnitTestRunner.TestFixture.get_Name [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.TestFixture.get_OneTimeSetUp [method]: unit -> System.Reflection.MethodInfo option
|
WoofWare.NUnitTestRunner.TestFixture.get_OneTimeSetUp [method]: unit -> System.Reflection.MethodInfo option
|
||||||
@@ -267,7 +371,14 @@ WoofWare.NUnitTestRunner.TestFixture.Tests [property]: [read-only] WoofWare.NUni
|
|||||||
WoofWare.NUnitTestRunner.TestFixture.Type [property]: [read-only] System.Type
|
WoofWare.NUnitTestRunner.TestFixture.Type [property]: [read-only] System.Type
|
||||||
WoofWare.NUnitTestRunner.TestFixtureModule inherit obj
|
WoofWare.NUnitTestRunner.TestFixtureModule inherit obj
|
||||||
WoofWare.NUnitTestRunner.TestFixtureModule.parse [static method]: System.Type -> WoofWare.NUnitTestRunner.TestFixture
|
WoofWare.NUnitTestRunner.TestFixtureModule.parse [static method]: System.Type -> WoofWare.NUnitTestRunner.TestFixture
|
||||||
WoofWare.NUnitTestRunner.TestFixtureModule.run [static method]: WoofWare.NUnitTestRunner.ITestProgress -> (WoofWare.NUnitTestRunner.TestFixture -> WoofWare.NUnitTestRunner.SingleTestMethod -> bool) -> WoofWare.NUnitTestRunner.TestFixture -> WoofWare.NUnitTestRunner.FixtureRunResults list
|
WoofWare.NUnitTestRunner.TestFixtureModule.run [static method]: WoofWare.NUnitTestRunner.TestContexts -> WoofWare.NUnitTestRunner.ParallelQueue -> WoofWare.NUnitTestRunner.ITestProgress -> (WoofWare.NUnitTestRunner.TestFixture -> WoofWare.NUnitTestRunner.SingleTestMethod -> bool) -> WoofWare.NUnitTestRunner.TestFixture -> WoofWare.NUnitTestRunner.FixtureRunResults list System.Threading.Tasks.Task
|
||||||
|
WoofWare.NUnitTestRunner.TestFixtureModule.runOneFixture [static method]: WoofWare.NUnitTestRunner.TestContexts -> WoofWare.NUnitTestRunner.ParallelQueue -> WoofWare.NUnitTestRunner.ITestProgress -> (WoofWare.NUnitTestRunner.TestFixture -> WoofWare.NUnitTestRunner.SingleTestMethod -> bool) -> string -> obj -> WoofWare.NUnitTestRunner.TestFixture -> WoofWare.NUnitTestRunner.FixtureRunResults System.Threading.Tasks.Task
|
||||||
|
WoofWare.NUnitTestRunner.TestFixtureRunningToken inherit obj, implements WoofWare.NUnitTestRunner.TestFixtureRunningToken System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
|
WoofWare.NUnitTestRunner.TestFixtureRunningToken.Equals [method]: (WoofWare.NUnitTestRunner.TestFixtureRunningToken, System.Collections.IEqualityComparer) -> bool
|
||||||
|
WoofWare.NUnitTestRunner.TestFixtureSetupToken inherit obj, implements WoofWare.NUnitTestRunner.TestFixtureSetupToken System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
|
WoofWare.NUnitTestRunner.TestFixtureSetupToken.Equals [method]: (WoofWare.NUnitTestRunner.TestFixtureSetupToken, System.Collections.IEqualityComparer) -> bool
|
||||||
|
WoofWare.NUnitTestRunner.TestFixtureTearDownToken inherit obj, implements WoofWare.NUnitTestRunner.TestFixtureTearDownToken System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
|
WoofWare.NUnitTestRunner.TestFixtureTearDownToken.Equals [method]: (WoofWare.NUnitTestRunner.TestFixtureTearDownToken, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TestKind inherit obj, implements WoofWare.NUnitTestRunner.TestKind System.IEquatable, System.Collections.IStructuralEquatable - union type with 3 cases
|
WoofWare.NUnitTestRunner.TestKind inherit obj, implements WoofWare.NUnitTestRunner.TestKind System.IEquatable, System.Collections.IStructuralEquatable - union type with 3 cases
|
||||||
WoofWare.NUnitTestRunner.TestKind+Data inherit WoofWare.NUnitTestRunner.TestKind
|
WoofWare.NUnitTestRunner.TestKind+Data inherit WoofWare.NUnitTestRunner.TestKind
|
||||||
WoofWare.NUnitTestRunner.TestKind+Data.get_Item [method]: unit -> obj list list
|
WoofWare.NUnitTestRunner.TestKind+Data.get_Item [method]: unit -> obj list list
|
||||||
@@ -279,6 +390,7 @@ WoofWare.NUnitTestRunner.TestKind+Tags inherit obj
|
|||||||
WoofWare.NUnitTestRunner.TestKind+Tags.Data [static field]: int = 2
|
WoofWare.NUnitTestRunner.TestKind+Tags.Data [static field]: int = 2
|
||||||
WoofWare.NUnitTestRunner.TestKind+Tags.Single [static field]: int = 0
|
WoofWare.NUnitTestRunner.TestKind+Tags.Single [static field]: int = 0
|
||||||
WoofWare.NUnitTestRunner.TestKind+Tags.Source [static field]: int = 1
|
WoofWare.NUnitTestRunner.TestKind+Tags.Source [static field]: int = 1
|
||||||
|
WoofWare.NUnitTestRunner.TestKind.Equals [method]: (WoofWare.NUnitTestRunner.TestKind, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TestKind.get_IsData [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestKind.get_IsData [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.TestKind.get_IsSingle [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestKind.get_IsSingle [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.TestKind.get_IsSource [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestKind.get_IsSource [method]: unit -> bool
|
||||||
@@ -301,6 +413,7 @@ WoofWare.NUnitTestRunner.TestMemberFailure+Malformed.reasons [property]: [read-o
|
|||||||
WoofWare.NUnitTestRunner.TestMemberFailure+Tags inherit obj
|
WoofWare.NUnitTestRunner.TestMemberFailure+Tags inherit obj
|
||||||
WoofWare.NUnitTestRunner.TestMemberFailure+Tags.Failed [static field]: int = 1
|
WoofWare.NUnitTestRunner.TestMemberFailure+Tags.Failed [static field]: int = 1
|
||||||
WoofWare.NUnitTestRunner.TestMemberFailure+Tags.Malformed [static field]: int = 0
|
WoofWare.NUnitTestRunner.TestMemberFailure+Tags.Malformed [static field]: int = 0
|
||||||
|
WoofWare.NUnitTestRunner.TestMemberFailure.Equals [method]: (WoofWare.NUnitTestRunner.TestMemberFailure, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TestMemberFailure.get_IsFailed [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestMemberFailure.get_IsFailed [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.TestMemberFailure.get_IsMalformed [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestMemberFailure.get_IsMalformed [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.TestMemberFailure.get_Tag [method]: unit -> int
|
WoofWare.NUnitTestRunner.TestMemberFailure.get_Tag [method]: unit -> int
|
||||||
@@ -324,6 +437,7 @@ WoofWare.NUnitTestRunner.TestMemberSuccess+Tags.Explicit [static field]: int = 2
|
|||||||
WoofWare.NUnitTestRunner.TestMemberSuccess+Tags.Ignored [static field]: int = 1
|
WoofWare.NUnitTestRunner.TestMemberSuccess+Tags.Ignored [static field]: int = 1
|
||||||
WoofWare.NUnitTestRunner.TestMemberSuccess+Tags.Inconclusive [static field]: int = 3
|
WoofWare.NUnitTestRunner.TestMemberSuccess+Tags.Inconclusive [static field]: int = 3
|
||||||
WoofWare.NUnitTestRunner.TestMemberSuccess+Tags.Ok [static field]: int = 0
|
WoofWare.NUnitTestRunner.TestMemberSuccess+Tags.Ok [static field]: int = 0
|
||||||
|
WoofWare.NUnitTestRunner.TestMemberSuccess.Equals [method]: (WoofWare.NUnitTestRunner.TestMemberSuccess, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TestMemberSuccess.get_IsExplicit [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestMemberSuccess.get_IsExplicit [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.TestMemberSuccess.get_IsIgnored [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestMemberSuccess.get_IsIgnored [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.TestMemberSuccess.get_IsInconclusive [method]: unit -> bool
|
WoofWare.NUnitTestRunner.TestMemberSuccess.get_IsInconclusive [method]: unit -> bool
|
||||||
@@ -341,6 +455,7 @@ WoofWare.NUnitTestRunner.TestMemberSuccess.Ok [static property]: [read-only] Woo
|
|||||||
WoofWare.NUnitTestRunner.TestMemberSuccess.Tag [property]: [read-only] int
|
WoofWare.NUnitTestRunner.TestMemberSuccess.Tag [property]: [read-only] int
|
||||||
WoofWare.NUnitTestRunner.TestProgress inherit obj
|
WoofWare.NUnitTestRunner.TestProgress inherit obj
|
||||||
WoofWare.NUnitTestRunner.TestProgress.toStderr [static method]: unit -> WoofWare.NUnitTestRunner.ITestProgress
|
WoofWare.NUnitTestRunner.TestProgress.toStderr [static method]: unit -> WoofWare.NUnitTestRunner.ITestProgress
|
||||||
|
WoofWare.NUnitTestRunner.TestProgress.toWriter [static method]: System.IO.TextWriter -> WoofWare.NUnitTestRunner.ITestProgress
|
||||||
WoofWare.NUnitTestRunner.TrxCounters inherit obj, implements WoofWare.NUnitTestRunner.TrxCounters System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxCounters inherit obj, implements WoofWare.NUnitTestRunner.TrxCounters System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxCounters..ctor [constructor]: (System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32)
|
WoofWare.NUnitTestRunner.TrxCounters..ctor [constructor]: (System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32, System.UInt32)
|
||||||
WoofWare.NUnitTestRunner.TrxCounters.Aborted [property]: [read-only] System.UInt32
|
WoofWare.NUnitTestRunner.TrxCounters.Aborted [property]: [read-only] System.UInt32
|
||||||
@@ -350,6 +465,7 @@ WoofWare.NUnitTestRunner.TrxCounters.AddNotExecuted [method]: unit -> WoofWare.N
|
|||||||
WoofWare.NUnitTestRunner.TrxCounters.AddPassed [method]: unit -> WoofWare.NUnitTestRunner.TrxCounters
|
WoofWare.NUnitTestRunner.TrxCounters.AddPassed [method]: unit -> WoofWare.NUnitTestRunner.TrxCounters
|
||||||
WoofWare.NUnitTestRunner.TrxCounters.Completed [property]: [read-only] System.UInt32
|
WoofWare.NUnitTestRunner.TrxCounters.Completed [property]: [read-only] System.UInt32
|
||||||
WoofWare.NUnitTestRunner.TrxCounters.Disconnected [property]: [read-only] System.UInt32
|
WoofWare.NUnitTestRunner.TrxCounters.Disconnected [property]: [read-only] System.UInt32
|
||||||
|
WoofWare.NUnitTestRunner.TrxCounters.Equals [method]: (WoofWare.NUnitTestRunner.TrxCounters, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxCounters.Errors [property]: [read-only] System.UInt32
|
WoofWare.NUnitTestRunner.TrxCounters.Errors [property]: [read-only] System.UInt32
|
||||||
WoofWare.NUnitTestRunner.TrxCounters.Executed [property]: [read-only] System.UInt32
|
WoofWare.NUnitTestRunner.TrxCounters.Executed [property]: [read-only] System.UInt32
|
||||||
WoofWare.NUnitTestRunner.TrxCounters.Failed [property]: [read-only] System.UInt32
|
WoofWare.NUnitTestRunner.TrxCounters.Failed [property]: [read-only] System.UInt32
|
||||||
@@ -383,16 +499,19 @@ WoofWare.NUnitTestRunner.TrxCounters.Warning [property]: [read-only] System.UInt
|
|||||||
WoofWare.NUnitTestRunner.TrxCounters.Zero [static property]: [read-only] WoofWare.NUnitTestRunner.TrxCounters
|
WoofWare.NUnitTestRunner.TrxCounters.Zero [static property]: [read-only] WoofWare.NUnitTestRunner.TrxCounters
|
||||||
WoofWare.NUnitTestRunner.TrxDeployment inherit obj, implements WoofWare.NUnitTestRunner.TrxDeployment System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxDeployment inherit obj, implements WoofWare.NUnitTestRunner.TrxDeployment System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxDeployment..ctor [constructor]: string
|
WoofWare.NUnitTestRunner.TrxDeployment..ctor [constructor]: string
|
||||||
|
WoofWare.NUnitTestRunner.TrxDeployment.Equals [method]: (WoofWare.NUnitTestRunner.TrxDeployment, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxDeployment.get_RunDeploymentRoot [method]: unit -> string
|
WoofWare.NUnitTestRunner.TrxDeployment.get_RunDeploymentRoot [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.TrxDeployment.RunDeploymentRoot [property]: [read-only] string
|
WoofWare.NUnitTestRunner.TrxDeployment.RunDeploymentRoot [property]: [read-only] string
|
||||||
WoofWare.NUnitTestRunner.TrxErrorInfo inherit obj, implements WoofWare.NUnitTestRunner.TrxErrorInfo System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxErrorInfo inherit obj, implements WoofWare.NUnitTestRunner.TrxErrorInfo System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxErrorInfo..ctor [constructor]: (string option, string option)
|
WoofWare.NUnitTestRunner.TrxErrorInfo..ctor [constructor]: (string option, string option)
|
||||||
|
WoofWare.NUnitTestRunner.TrxErrorInfo.Equals [method]: (WoofWare.NUnitTestRunner.TrxErrorInfo, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxErrorInfo.get_Message [method]: unit -> string option
|
WoofWare.NUnitTestRunner.TrxErrorInfo.get_Message [method]: unit -> string option
|
||||||
WoofWare.NUnitTestRunner.TrxErrorInfo.get_StackTrace [method]: unit -> string option
|
WoofWare.NUnitTestRunner.TrxErrorInfo.get_StackTrace [method]: unit -> string option
|
||||||
WoofWare.NUnitTestRunner.TrxErrorInfo.Message [property]: [read-only] string option
|
WoofWare.NUnitTestRunner.TrxErrorInfo.Message [property]: [read-only] string option
|
||||||
WoofWare.NUnitTestRunner.TrxErrorInfo.StackTrace [property]: [read-only] string option
|
WoofWare.NUnitTestRunner.TrxErrorInfo.StackTrace [property]: [read-only] string option
|
||||||
WoofWare.NUnitTestRunner.TrxExecution inherit obj, implements WoofWare.NUnitTestRunner.TrxExecution System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxExecution inherit obj, implements WoofWare.NUnitTestRunner.TrxExecution System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxExecution..ctor [constructor]: System.Guid
|
WoofWare.NUnitTestRunner.TrxExecution..ctor [constructor]: System.Guid
|
||||||
|
WoofWare.NUnitTestRunner.TrxExecution.Equals [method]: (WoofWare.NUnitTestRunner.TrxExecution, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxExecution.get_Id [method]: unit -> System.Guid
|
WoofWare.NUnitTestRunner.TrxExecution.get_Id [method]: unit -> System.Guid
|
||||||
WoofWare.NUnitTestRunner.TrxExecution.Id [property]: [read-only] System.Guid
|
WoofWare.NUnitTestRunner.TrxExecution.Id [property]: [read-only] System.Guid
|
||||||
WoofWare.NUnitTestRunner.TrxOutcome inherit obj, implements WoofWare.NUnitTestRunner.TrxOutcome System.IEquatable, System.Collections.IStructuralEquatable - union type with 3 cases
|
WoofWare.NUnitTestRunner.TrxOutcome inherit obj, implements WoofWare.NUnitTestRunner.TrxOutcome System.IEquatable, System.Collections.IStructuralEquatable - union type with 3 cases
|
||||||
@@ -401,6 +520,7 @@ WoofWare.NUnitTestRunner.TrxOutcome+Tags.Completed [static field]: int = 0
|
|||||||
WoofWare.NUnitTestRunner.TrxOutcome+Tags.Failed [static field]: int = 2
|
WoofWare.NUnitTestRunner.TrxOutcome+Tags.Failed [static field]: int = 2
|
||||||
WoofWare.NUnitTestRunner.TrxOutcome+Tags.Warning [static field]: int = 1
|
WoofWare.NUnitTestRunner.TrxOutcome+Tags.Warning [static field]: int = 1
|
||||||
WoofWare.NUnitTestRunner.TrxOutcome.Completed [static property]: [read-only] WoofWare.NUnitTestRunner.TrxOutcome
|
WoofWare.NUnitTestRunner.TrxOutcome.Completed [static property]: [read-only] WoofWare.NUnitTestRunner.TrxOutcome
|
||||||
|
WoofWare.NUnitTestRunner.TrxOutcome.Equals [method]: (WoofWare.NUnitTestRunner.TrxOutcome, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxOutcome.Failed [static property]: [read-only] WoofWare.NUnitTestRunner.TrxOutcome
|
WoofWare.NUnitTestRunner.TrxOutcome.Failed [static property]: [read-only] WoofWare.NUnitTestRunner.TrxOutcome
|
||||||
WoofWare.NUnitTestRunner.TrxOutcome.get_Completed [static method]: unit -> WoofWare.NUnitTestRunner.TrxOutcome
|
WoofWare.NUnitTestRunner.TrxOutcome.get_Completed [static method]: unit -> WoofWare.NUnitTestRunner.TrxOutcome
|
||||||
WoofWare.NUnitTestRunner.TrxOutcome.get_Failed [static method]: unit -> WoofWare.NUnitTestRunner.TrxOutcome
|
WoofWare.NUnitTestRunner.TrxOutcome.get_Failed [static method]: unit -> WoofWare.NUnitTestRunner.TrxOutcome
|
||||||
@@ -417,6 +537,7 @@ WoofWare.NUnitTestRunner.TrxOutcome.Tag [property]: [read-only] int
|
|||||||
WoofWare.NUnitTestRunner.TrxOutcome.Warning [static property]: [read-only] WoofWare.NUnitTestRunner.TrxOutcome
|
WoofWare.NUnitTestRunner.TrxOutcome.Warning [static property]: [read-only] WoofWare.NUnitTestRunner.TrxOutcome
|
||||||
WoofWare.NUnitTestRunner.TrxOutput inherit obj, implements WoofWare.NUnitTestRunner.TrxOutput System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxOutput inherit obj, implements WoofWare.NUnitTestRunner.TrxOutput System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxOutput..ctor [constructor]: (string option, string option, WoofWare.NUnitTestRunner.TrxErrorInfo option)
|
WoofWare.NUnitTestRunner.TrxOutput..ctor [constructor]: (string option, string option, WoofWare.NUnitTestRunner.TrxErrorInfo option)
|
||||||
|
WoofWare.NUnitTestRunner.TrxOutput.Equals [method]: (WoofWare.NUnitTestRunner.TrxOutput, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxOutput.ErrorInfo [property]: [read-only] WoofWare.NUnitTestRunner.TrxErrorInfo option
|
WoofWare.NUnitTestRunner.TrxOutput.ErrorInfo [property]: [read-only] WoofWare.NUnitTestRunner.TrxErrorInfo option
|
||||||
WoofWare.NUnitTestRunner.TrxOutput.get_ErrorInfo [method]: unit -> WoofWare.NUnitTestRunner.TrxErrorInfo option
|
WoofWare.NUnitTestRunner.TrxOutput.get_ErrorInfo [method]: unit -> WoofWare.NUnitTestRunner.TrxErrorInfo option
|
||||||
WoofWare.NUnitTestRunner.TrxOutput.get_StdErr [method]: unit -> string option
|
WoofWare.NUnitTestRunner.TrxOutput.get_StdErr [method]: unit -> string option
|
||||||
@@ -425,6 +546,7 @@ WoofWare.NUnitTestRunner.TrxOutput.StdErr [property]: [read-only] string option
|
|||||||
WoofWare.NUnitTestRunner.TrxOutput.StdOut [property]: [read-only] string option
|
WoofWare.NUnitTestRunner.TrxOutput.StdOut [property]: [read-only] string option
|
||||||
WoofWare.NUnitTestRunner.TrxReport inherit obj, implements WoofWare.NUnitTestRunner.TrxReport System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxReport inherit obj, implements WoofWare.NUnitTestRunner.TrxReport System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxReport..ctor [constructor]: (System.Guid, string, WoofWare.NUnitTestRunner.TrxReportTimes, WoofWare.NUnitTestRunner.TrxTestSettings, WoofWare.NUnitTestRunner.TrxUnitTestResult list, WoofWare.NUnitTestRunner.TrxUnitTest list, WoofWare.NUnitTestRunner.TrxTestEntry list, WoofWare.NUnitTestRunner.TrxTestListEntry list, WoofWare.NUnitTestRunner.TrxResultsSummary)
|
WoofWare.NUnitTestRunner.TrxReport..ctor [constructor]: (System.Guid, string, WoofWare.NUnitTestRunner.TrxReportTimes, WoofWare.NUnitTestRunner.TrxTestSettings, WoofWare.NUnitTestRunner.TrxUnitTestResult list, WoofWare.NUnitTestRunner.TrxUnitTest list, WoofWare.NUnitTestRunner.TrxTestEntry list, WoofWare.NUnitTestRunner.TrxTestListEntry list, WoofWare.NUnitTestRunner.TrxResultsSummary)
|
||||||
|
WoofWare.NUnitTestRunner.TrxReport.Equals [method]: (WoofWare.NUnitTestRunner.TrxReport, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxReport.get_Id [method]: unit -> System.Guid
|
WoofWare.NUnitTestRunner.TrxReport.get_Id [method]: unit -> System.Guid
|
||||||
WoofWare.NUnitTestRunner.TrxReport.get_Name [method]: unit -> string
|
WoofWare.NUnitTestRunner.TrxReport.get_Name [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.TrxReport.get_Results [method]: unit -> WoofWare.NUnitTestRunner.TrxUnitTestResult list
|
WoofWare.NUnitTestRunner.TrxReport.get_Results [method]: unit -> WoofWare.NUnitTestRunner.TrxUnitTestResult list
|
||||||
@@ -449,6 +571,7 @@ WoofWare.NUnitTestRunner.TrxReportModule.toXml [static method]: WoofWare.NUnitTe
|
|||||||
WoofWare.NUnitTestRunner.TrxReportTimes inherit obj, implements WoofWare.NUnitTestRunner.TrxReportTimes System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxReportTimes inherit obj, implements WoofWare.NUnitTestRunner.TrxReportTimes System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxReportTimes..ctor [constructor]: (System.DateTimeOffset, System.DateTimeOffset, System.DateTimeOffset, System.DateTimeOffset)
|
WoofWare.NUnitTestRunner.TrxReportTimes..ctor [constructor]: (System.DateTimeOffset, System.DateTimeOffset, System.DateTimeOffset, System.DateTimeOffset)
|
||||||
WoofWare.NUnitTestRunner.TrxReportTimes.Creation [property]: [read-only] System.DateTimeOffset
|
WoofWare.NUnitTestRunner.TrxReportTimes.Creation [property]: [read-only] System.DateTimeOffset
|
||||||
|
WoofWare.NUnitTestRunner.TrxReportTimes.Equals [method]: (WoofWare.NUnitTestRunner.TrxReportTimes, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxReportTimes.Finish [property]: [read-only] System.DateTimeOffset
|
WoofWare.NUnitTestRunner.TrxReportTimes.Finish [property]: [read-only] System.DateTimeOffset
|
||||||
WoofWare.NUnitTestRunner.TrxReportTimes.get_Creation [method]: unit -> System.DateTimeOffset
|
WoofWare.NUnitTestRunner.TrxReportTimes.get_Creation [method]: unit -> System.DateTimeOffset
|
||||||
WoofWare.NUnitTestRunner.TrxReportTimes.get_Finish [method]: unit -> System.DateTimeOffset
|
WoofWare.NUnitTestRunner.TrxReportTimes.get_Finish [method]: unit -> System.DateTimeOffset
|
||||||
@@ -459,6 +582,7 @@ WoofWare.NUnitTestRunner.TrxReportTimes.Start [property]: [read-only] System.Dat
|
|||||||
WoofWare.NUnitTestRunner.TrxResultsSummary inherit obj, implements WoofWare.NUnitTestRunner.TrxResultsSummary System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxResultsSummary inherit obj, implements WoofWare.NUnitTestRunner.TrxResultsSummary System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxResultsSummary..ctor [constructor]: (WoofWare.NUnitTestRunner.TrxOutcome, WoofWare.NUnitTestRunner.TrxCounters, WoofWare.NUnitTestRunner.TrxOutput, WoofWare.NUnitTestRunner.TrxRunInfo list)
|
WoofWare.NUnitTestRunner.TrxResultsSummary..ctor [constructor]: (WoofWare.NUnitTestRunner.TrxOutcome, WoofWare.NUnitTestRunner.TrxCounters, WoofWare.NUnitTestRunner.TrxOutput, WoofWare.NUnitTestRunner.TrxRunInfo list)
|
||||||
WoofWare.NUnitTestRunner.TrxResultsSummary.Counters [property]: [read-only] WoofWare.NUnitTestRunner.TrxCounters
|
WoofWare.NUnitTestRunner.TrxResultsSummary.Counters [property]: [read-only] WoofWare.NUnitTestRunner.TrxCounters
|
||||||
|
WoofWare.NUnitTestRunner.TrxResultsSummary.Equals [method]: (WoofWare.NUnitTestRunner.TrxResultsSummary, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxResultsSummary.get_Counters [method]: unit -> WoofWare.NUnitTestRunner.TrxCounters
|
WoofWare.NUnitTestRunner.TrxResultsSummary.get_Counters [method]: unit -> WoofWare.NUnitTestRunner.TrxCounters
|
||||||
WoofWare.NUnitTestRunner.TrxResultsSummary.get_Outcome [method]: unit -> WoofWare.NUnitTestRunner.TrxOutcome
|
WoofWare.NUnitTestRunner.TrxResultsSummary.get_Outcome [method]: unit -> WoofWare.NUnitTestRunner.TrxOutcome
|
||||||
WoofWare.NUnitTestRunner.TrxResultsSummary.get_Output [method]: unit -> WoofWare.NUnitTestRunner.TrxOutput
|
WoofWare.NUnitTestRunner.TrxResultsSummary.get_Output [method]: unit -> WoofWare.NUnitTestRunner.TrxOutput
|
||||||
@@ -469,6 +593,7 @@ WoofWare.NUnitTestRunner.TrxResultsSummary.RunInfos [property]: [read-only] Woof
|
|||||||
WoofWare.NUnitTestRunner.TrxRunInfo inherit obj, implements WoofWare.NUnitTestRunner.TrxRunInfo System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxRunInfo inherit obj, implements WoofWare.NUnitTestRunner.TrxRunInfo System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxRunInfo..ctor [constructor]: (string, WoofWare.NUnitTestRunner.TrxOutcome, System.DateTimeOffset, string)
|
WoofWare.NUnitTestRunner.TrxRunInfo..ctor [constructor]: (string, WoofWare.NUnitTestRunner.TrxOutcome, System.DateTimeOffset, string)
|
||||||
WoofWare.NUnitTestRunner.TrxRunInfo.ComputerName [property]: [read-only] string
|
WoofWare.NUnitTestRunner.TrxRunInfo.ComputerName [property]: [read-only] string
|
||||||
|
WoofWare.NUnitTestRunner.TrxRunInfo.Equals [method]: (WoofWare.NUnitTestRunner.TrxRunInfo, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxRunInfo.get_ComputerName [method]: unit -> string
|
WoofWare.NUnitTestRunner.TrxRunInfo.get_ComputerName [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.TrxRunInfo.get_Outcome [method]: unit -> WoofWare.NUnitTestRunner.TrxOutcome
|
WoofWare.NUnitTestRunner.TrxRunInfo.get_Outcome [method]: unit -> WoofWare.NUnitTestRunner.TrxOutcome
|
||||||
WoofWare.NUnitTestRunner.TrxRunInfo.get_Text [method]: unit -> string
|
WoofWare.NUnitTestRunner.TrxRunInfo.get_Text [method]: unit -> string
|
||||||
@@ -478,6 +603,7 @@ WoofWare.NUnitTestRunner.TrxRunInfo.Text [property]: [read-only] string
|
|||||||
WoofWare.NUnitTestRunner.TrxRunInfo.Timestamp [property]: [read-only] System.DateTimeOffset
|
WoofWare.NUnitTestRunner.TrxRunInfo.Timestamp [property]: [read-only] System.DateTimeOffset
|
||||||
WoofWare.NUnitTestRunner.TrxTestEntry inherit obj, implements WoofWare.NUnitTestRunner.TrxTestEntry System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxTestEntry inherit obj, implements WoofWare.NUnitTestRunner.TrxTestEntry System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxTestEntry..ctor [constructor]: (System.Guid, System.Guid, System.Guid)
|
WoofWare.NUnitTestRunner.TrxTestEntry..ctor [constructor]: (System.Guid, System.Guid, System.Guid)
|
||||||
|
WoofWare.NUnitTestRunner.TrxTestEntry.Equals [method]: (WoofWare.NUnitTestRunner.TrxTestEntry, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxTestEntry.ExecutionId [property]: [read-only] System.Guid
|
WoofWare.NUnitTestRunner.TrxTestEntry.ExecutionId [property]: [read-only] System.Guid
|
||||||
WoofWare.NUnitTestRunner.TrxTestEntry.get_ExecutionId [method]: unit -> System.Guid
|
WoofWare.NUnitTestRunner.TrxTestEntry.get_ExecutionId [method]: unit -> System.Guid
|
||||||
WoofWare.NUnitTestRunner.TrxTestEntry.get_TestId [method]: unit -> System.Guid
|
WoofWare.NUnitTestRunner.TrxTestEntry.get_TestId [method]: unit -> System.Guid
|
||||||
@@ -486,6 +612,7 @@ WoofWare.NUnitTestRunner.TrxTestEntry.TestId [property]: [read-only] System.Guid
|
|||||||
WoofWare.NUnitTestRunner.TrxTestEntry.TestListId [property]: [read-only] System.Guid
|
WoofWare.NUnitTestRunner.TrxTestEntry.TestListId [property]: [read-only] System.Guid
|
||||||
WoofWare.NUnitTestRunner.TrxTestListEntry inherit obj, implements WoofWare.NUnitTestRunner.TrxTestListEntry System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxTestListEntry inherit obj, implements WoofWare.NUnitTestRunner.TrxTestListEntry System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxTestListEntry..ctor [constructor]: (string, System.Guid)
|
WoofWare.NUnitTestRunner.TrxTestListEntry..ctor [constructor]: (string, System.Guid)
|
||||||
|
WoofWare.NUnitTestRunner.TrxTestListEntry.Equals [method]: (WoofWare.NUnitTestRunner.TrxTestListEntry, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxTestListEntry.get_Id [method]: unit -> System.Guid
|
WoofWare.NUnitTestRunner.TrxTestListEntry.get_Id [method]: unit -> System.Guid
|
||||||
WoofWare.NUnitTestRunner.TrxTestListEntry.get_Name [method]: unit -> string
|
WoofWare.NUnitTestRunner.TrxTestListEntry.get_Name [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.TrxTestListEntry.Id [property]: [read-only] System.Guid
|
WoofWare.NUnitTestRunner.TrxTestListEntry.Id [property]: [read-only] System.Guid
|
||||||
@@ -495,6 +622,7 @@ WoofWare.NUnitTestRunner.TrxTestMethod..ctor [constructor]: (string, System.Uri,
|
|||||||
WoofWare.NUnitTestRunner.TrxTestMethod.AdapterTypeName [property]: [read-only] System.Uri
|
WoofWare.NUnitTestRunner.TrxTestMethod.AdapterTypeName [property]: [read-only] System.Uri
|
||||||
WoofWare.NUnitTestRunner.TrxTestMethod.ClassName [property]: [read-only] string
|
WoofWare.NUnitTestRunner.TrxTestMethod.ClassName [property]: [read-only] string
|
||||||
WoofWare.NUnitTestRunner.TrxTestMethod.CodeBase [property]: [read-only] string
|
WoofWare.NUnitTestRunner.TrxTestMethod.CodeBase [property]: [read-only] string
|
||||||
|
WoofWare.NUnitTestRunner.TrxTestMethod.Equals [method]: (WoofWare.NUnitTestRunner.TrxTestMethod, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxTestMethod.get_AdapterTypeName [method]: unit -> System.Uri
|
WoofWare.NUnitTestRunner.TrxTestMethod.get_AdapterTypeName [method]: unit -> System.Uri
|
||||||
WoofWare.NUnitTestRunner.TrxTestMethod.get_ClassName [method]: unit -> string
|
WoofWare.NUnitTestRunner.TrxTestMethod.get_ClassName [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.TrxTestMethod.get_CodeBase [method]: unit -> string
|
WoofWare.NUnitTestRunner.TrxTestMethod.get_CodeBase [method]: unit -> string
|
||||||
@@ -506,6 +634,7 @@ WoofWare.NUnitTestRunner.TrxTestOutcome+Tags.Failed [static field]: int = 1
|
|||||||
WoofWare.NUnitTestRunner.TrxTestOutcome+Tags.Inconclusive [static field]: int = 3
|
WoofWare.NUnitTestRunner.TrxTestOutcome+Tags.Inconclusive [static field]: int = 3
|
||||||
WoofWare.NUnitTestRunner.TrxTestOutcome+Tags.NotExecuted [static field]: int = 2
|
WoofWare.NUnitTestRunner.TrxTestOutcome+Tags.NotExecuted [static field]: int = 2
|
||||||
WoofWare.NUnitTestRunner.TrxTestOutcome+Tags.Passed [static field]: int = 0
|
WoofWare.NUnitTestRunner.TrxTestOutcome+Tags.Passed [static field]: int = 0
|
||||||
|
WoofWare.NUnitTestRunner.TrxTestOutcome.Equals [method]: (WoofWare.NUnitTestRunner.TrxTestOutcome, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxTestOutcome.Failed [static property]: [read-only] WoofWare.NUnitTestRunner.TrxTestOutcome
|
WoofWare.NUnitTestRunner.TrxTestOutcome.Failed [static property]: [read-only] WoofWare.NUnitTestRunner.TrxTestOutcome
|
||||||
WoofWare.NUnitTestRunner.TrxTestOutcome.get_Failed [static method]: unit -> WoofWare.NUnitTestRunner.TrxTestOutcome
|
WoofWare.NUnitTestRunner.TrxTestOutcome.get_Failed [static method]: unit -> WoofWare.NUnitTestRunner.TrxTestOutcome
|
||||||
WoofWare.NUnitTestRunner.TrxTestOutcome.get_Inconclusive [static method]: unit -> WoofWare.NUnitTestRunner.TrxTestOutcome
|
WoofWare.NUnitTestRunner.TrxTestOutcome.get_Inconclusive [static method]: unit -> WoofWare.NUnitTestRunner.TrxTestOutcome
|
||||||
@@ -528,6 +657,7 @@ WoofWare.NUnitTestRunner.TrxTestOutcome.Tag [property]: [read-only] int
|
|||||||
WoofWare.NUnitTestRunner.TrxTestSettings inherit obj, implements WoofWare.NUnitTestRunner.TrxTestSettings System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxTestSettings inherit obj, implements WoofWare.NUnitTestRunner.TrxTestSettings System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxTestSettings..ctor [constructor]: (string, System.Guid, WoofWare.NUnitTestRunner.TrxDeployment)
|
WoofWare.NUnitTestRunner.TrxTestSettings..ctor [constructor]: (string, System.Guid, WoofWare.NUnitTestRunner.TrxDeployment)
|
||||||
WoofWare.NUnitTestRunner.TrxTestSettings.Deployment [property]: [read-only] WoofWare.NUnitTestRunner.TrxDeployment
|
WoofWare.NUnitTestRunner.TrxTestSettings.Deployment [property]: [read-only] WoofWare.NUnitTestRunner.TrxDeployment
|
||||||
|
WoofWare.NUnitTestRunner.TrxTestSettings.Equals [method]: (WoofWare.NUnitTestRunner.TrxTestSettings, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxTestSettings.get_Deployment [method]: unit -> WoofWare.NUnitTestRunner.TrxDeployment
|
WoofWare.NUnitTestRunner.TrxTestSettings.get_Deployment [method]: unit -> WoofWare.NUnitTestRunner.TrxDeployment
|
||||||
WoofWare.NUnitTestRunner.TrxTestSettings.get_Id [method]: unit -> System.Guid
|
WoofWare.NUnitTestRunner.TrxTestSettings.get_Id [method]: unit -> System.Guid
|
||||||
WoofWare.NUnitTestRunner.TrxTestSettings.get_Name [method]: unit -> string
|
WoofWare.NUnitTestRunner.TrxTestSettings.get_Name [method]: unit -> string
|
||||||
@@ -535,6 +665,7 @@ WoofWare.NUnitTestRunner.TrxTestSettings.Id [property]: [read-only] System.Guid
|
|||||||
WoofWare.NUnitTestRunner.TrxTestSettings.Name [property]: [read-only] string
|
WoofWare.NUnitTestRunner.TrxTestSettings.Name [property]: [read-only] string
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTest inherit obj, implements WoofWare.NUnitTestRunner.TrxUnitTest System.IEquatable, System.Collections.IStructuralEquatable
|
WoofWare.NUnitTestRunner.TrxUnitTest inherit obj, implements WoofWare.NUnitTestRunner.TrxUnitTest System.IEquatable, System.Collections.IStructuralEquatable
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTest..ctor [constructor]: (string, string, System.Guid, WoofWare.NUnitTestRunner.TrxExecution, WoofWare.NUnitTestRunner.TrxTestMethod)
|
WoofWare.NUnitTestRunner.TrxUnitTest..ctor [constructor]: (string, string, System.Guid, WoofWare.NUnitTestRunner.TrxExecution, WoofWare.NUnitTestRunner.TrxTestMethod)
|
||||||
|
WoofWare.NUnitTestRunner.TrxUnitTest.Equals [method]: (WoofWare.NUnitTestRunner.TrxUnitTest, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTest.Execution [property]: [read-only] WoofWare.NUnitTestRunner.TrxExecution
|
WoofWare.NUnitTestRunner.TrxUnitTest.Execution [property]: [read-only] WoofWare.NUnitTestRunner.TrxExecution
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTest.get_Execution [method]: unit -> WoofWare.NUnitTestRunner.TrxExecution
|
WoofWare.NUnitTestRunner.TrxUnitTest.get_Execution [method]: unit -> WoofWare.NUnitTestRunner.TrxExecution
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTest.get_Id [method]: unit -> System.Guid
|
WoofWare.NUnitTestRunner.TrxUnitTest.get_Id [method]: unit -> System.Guid
|
||||||
@@ -550,6 +681,7 @@ WoofWare.NUnitTestRunner.TrxUnitTestResult..ctor [constructor]: (System.Guid, Sy
|
|||||||
WoofWare.NUnitTestRunner.TrxUnitTestResult.ComputerName [property]: [read-only] string
|
WoofWare.NUnitTestRunner.TrxUnitTestResult.ComputerName [property]: [read-only] string
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTestResult.Duration [property]: [read-only] System.TimeSpan
|
WoofWare.NUnitTestRunner.TrxUnitTestResult.Duration [property]: [read-only] System.TimeSpan
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTestResult.EndTime [property]: [read-only] System.DateTimeOffset
|
WoofWare.NUnitTestRunner.TrxUnitTestResult.EndTime [property]: [read-only] System.DateTimeOffset
|
||||||
|
WoofWare.NUnitTestRunner.TrxUnitTestResult.Equals [method]: (WoofWare.NUnitTestRunner.TrxUnitTestResult, System.Collections.IEqualityComparer) -> bool
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTestResult.ExecutionId [property]: [read-only] System.Guid
|
WoofWare.NUnitTestRunner.TrxUnitTestResult.ExecutionId [property]: [read-only] System.Guid
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTestResult.get_ComputerName [method]: unit -> string
|
WoofWare.NUnitTestRunner.TrxUnitTestResult.get_ComputerName [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTestResult.get_Duration [method]: unit -> System.TimeSpan
|
WoofWare.NUnitTestRunner.TrxUnitTestResult.get_Duration [method]: unit -> System.TimeSpan
|
||||||
@@ -571,13 +703,21 @@ WoofWare.NUnitTestRunner.TrxUnitTestResult.TestId [property]: [read-only] System
|
|||||||
WoofWare.NUnitTestRunner.TrxUnitTestResult.TestListId [property]: [read-only] System.Guid
|
WoofWare.NUnitTestRunner.TrxUnitTestResult.TestListId [property]: [read-only] System.Guid
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTestResult.TestName [property]: [read-only] string
|
WoofWare.NUnitTestRunner.TrxUnitTestResult.TestName [property]: [read-only] string
|
||||||
WoofWare.NUnitTestRunner.TrxUnitTestResult.TestType [property]: [read-only] System.Guid
|
WoofWare.NUnitTestRunner.TrxUnitTestResult.TestType [property]: [read-only] System.Guid
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure inherit obj, implements WoofWare.NUnitTestRunner.UserMethodFailure System.IEquatable, System.Collections.IStructuralEquatable - union type with 2 cases
|
WoofWare.NUnitTestRunner.UserMethodFailure inherit obj, implements WoofWare.NUnitTestRunner.UserMethodFailure System.IEquatable, System.Collections.IStructuralEquatable - union type with 3 cases
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure+BadParameters inherit WoofWare.NUnitTestRunner.UserMethodFailure
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure+BadParameters.actual [property]: [read-only] obj []
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure+BadParameters.expected [property]: [read-only] System.Type []
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure+BadParameters.get_actual [method]: unit -> obj []
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure+BadParameters.get_expected [method]: unit -> System.Type []
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure+BadParameters.get_name [method]: unit -> string
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure+BadParameters.name [property]: [read-only] string
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+ReturnedNonUnit inherit WoofWare.NUnitTestRunner.UserMethodFailure
|
WoofWare.NUnitTestRunner.UserMethodFailure+ReturnedNonUnit inherit WoofWare.NUnitTestRunner.UserMethodFailure
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+ReturnedNonUnit.get_name [method]: unit -> string
|
WoofWare.NUnitTestRunner.UserMethodFailure+ReturnedNonUnit.get_name [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+ReturnedNonUnit.get_result [method]: unit -> obj
|
WoofWare.NUnitTestRunner.UserMethodFailure+ReturnedNonUnit.get_result [method]: unit -> obj
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+ReturnedNonUnit.name [property]: [read-only] string
|
WoofWare.NUnitTestRunner.UserMethodFailure+ReturnedNonUnit.name [property]: [read-only] string
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+ReturnedNonUnit.result [property]: [read-only] obj
|
WoofWare.NUnitTestRunner.UserMethodFailure+ReturnedNonUnit.result [property]: [read-only] obj
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+Tags inherit obj
|
WoofWare.NUnitTestRunner.UserMethodFailure+Tags inherit obj
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure+Tags.BadParameters [static field]: int = 2
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+Tags.ReturnedNonUnit [static field]: int = 0
|
WoofWare.NUnitTestRunner.UserMethodFailure+Tags.ReturnedNonUnit [static field]: int = 0
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+Tags.Threw [static field]: int = 1
|
WoofWare.NUnitTestRunner.UserMethodFailure+Tags.Threw [static field]: int = 1
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+Threw inherit WoofWare.NUnitTestRunner.UserMethodFailure
|
WoofWare.NUnitTestRunner.UserMethodFailure+Threw inherit WoofWare.NUnitTestRunner.UserMethodFailure
|
||||||
@@ -585,13 +725,17 @@ WoofWare.NUnitTestRunner.UserMethodFailure+Threw.get_Item2 [method]: unit -> Sys
|
|||||||
WoofWare.NUnitTestRunner.UserMethodFailure+Threw.get_name [method]: unit -> string
|
WoofWare.NUnitTestRunner.UserMethodFailure+Threw.get_name [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+Threw.Item2 [property]: [read-only] System.Exception
|
WoofWare.NUnitTestRunner.UserMethodFailure+Threw.Item2 [property]: [read-only] System.Exception
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure+Threw.name [property]: [read-only] string
|
WoofWare.NUnitTestRunner.UserMethodFailure+Threw.name [property]: [read-only] string
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure.Equals [method]: (WoofWare.NUnitTestRunner.UserMethodFailure, System.Collections.IEqualityComparer) -> bool
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure.get_IsBadParameters [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure.get_IsReturnedNonUnit [method]: unit -> bool
|
WoofWare.NUnitTestRunner.UserMethodFailure.get_IsReturnedNonUnit [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure.get_IsThrew [method]: unit -> bool
|
WoofWare.NUnitTestRunner.UserMethodFailure.get_IsThrew [method]: unit -> bool
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure.get_Name [method]: unit -> string
|
WoofWare.NUnitTestRunner.UserMethodFailure.get_Name [method]: unit -> string
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure.get_Tag [method]: unit -> int
|
WoofWare.NUnitTestRunner.UserMethodFailure.get_Tag [method]: unit -> int
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure.IsBadParameters [property]: [read-only] bool
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure.IsReturnedNonUnit [property]: [read-only] bool
|
WoofWare.NUnitTestRunner.UserMethodFailure.IsReturnedNonUnit [property]: [read-only] bool
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure.IsThrew [property]: [read-only] bool
|
WoofWare.NUnitTestRunner.UserMethodFailure.IsThrew [property]: [read-only] bool
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure.Name [property]: [read-only] string
|
WoofWare.NUnitTestRunner.UserMethodFailure.Name [property]: [read-only] string
|
||||||
|
WoofWare.NUnitTestRunner.UserMethodFailure.NewBadParameters [static method]: (string, System.Type [], obj []) -> WoofWare.NUnitTestRunner.UserMethodFailure
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure.NewReturnedNonUnit [static method]: (string, obj) -> WoofWare.NUnitTestRunner.UserMethodFailure
|
WoofWare.NUnitTestRunner.UserMethodFailure.NewReturnedNonUnit [static method]: (string, obj) -> WoofWare.NUnitTestRunner.UserMethodFailure
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure.NewThrew [static method]: (string, System.Exception) -> WoofWare.NUnitTestRunner.UserMethodFailure
|
WoofWare.NUnitTestRunner.UserMethodFailure.NewThrew [static method]: (string, System.Exception) -> WoofWare.NUnitTestRunner.UserMethodFailure
|
||||||
WoofWare.NUnitTestRunner.UserMethodFailure.Tag [property]: [read-only] int
|
WoofWare.NUnitTestRunner.UserMethodFailure.Tag [property]: [read-only] int
|
@@ -6,21 +6,9 @@ open System.Diagnostics
|
|||||||
open System.IO
|
open System.IO
|
||||||
open System.Reflection
|
open System.Reflection
|
||||||
open System.Threading
|
open System.Threading
|
||||||
|
open System.Threading.Tasks
|
||||||
open Microsoft.FSharp.Core
|
open Microsoft.FSharp.Core
|
||||||
|
|
||||||
type private StdoutSetter (newStdout : StreamWriter, newStderr : StreamWriter) =
|
|
||||||
let oldStdout = Console.Out
|
|
||||||
let oldStderr = Console.Error
|
|
||||||
|
|
||||||
do
|
|
||||||
Console.SetOut newStdout
|
|
||||||
Console.SetError newStderr
|
|
||||||
|
|
||||||
interface IDisposable with
|
|
||||||
member _.Dispose () =
|
|
||||||
Console.SetOut oldStdout
|
|
||||||
Console.SetError oldStderr
|
|
||||||
|
|
||||||
/// Information about the circumstances of a run of a single test.
|
/// Information about the circumstances of a run of a single test.
|
||||||
type IndividualTestRunMetadata =
|
type IndividualTestRunMetadata =
|
||||||
{
|
{
|
||||||
@@ -80,6 +68,8 @@ module TestFixture =
|
|||||||
///
|
///
|
||||||
/// This function does not throw.
|
/// This function does not throw.
|
||||||
let private runOne
|
let private runOne
|
||||||
|
(outputId : OutputStreamId)
|
||||||
|
(contexts : TestContexts)
|
||||||
(setUp : MethodInfo list)
|
(setUp : MethodInfo list)
|
||||||
(tearDown : MethodInfo list)
|
(tearDown : MethodInfo list)
|
||||||
(testId : Guid)
|
(testId : Guid)
|
||||||
@@ -100,8 +90,15 @@ module TestFixture =
|
|||||||
let result =
|
let result =
|
||||||
try
|
try
|
||||||
head.Invoke (containingObject, args) |> Ok
|
head.Invoke (containingObject, args) |> Ok
|
||||||
with :? TargetInvocationException as e ->
|
with
|
||||||
Error (UserMethodFailure.Threw (head.Name, e.InnerException))
|
| :? TargetInvocationException as e -> Error (UserMethodFailure.Threw (head.Name, e.InnerException))
|
||||||
|
| :? TargetParameterCountException ->
|
||||||
|
UserMethodFailure.BadParameters (
|
||||||
|
head.Name,
|
||||||
|
head.GetParameters () |> Array.map (fun pm -> pm.ParameterType),
|
||||||
|
args
|
||||||
|
)
|
||||||
|
|> Error
|
||||||
|
|
||||||
match result with
|
match result with
|
||||||
| Error e -> Error (wrap e)
|
| Error e -> Error (wrap e)
|
||||||
@@ -112,13 +109,6 @@ module TestFixture =
|
|||||||
|
|
||||||
let start = DateTimeOffset.Now
|
let start = DateTimeOffset.Now
|
||||||
|
|
||||||
use stdOutStream = new MemoryStream ()
|
|
||||||
use stdErrStream = new MemoryStream ()
|
|
||||||
use stdOut = new StreamWriter (stdOutStream)
|
|
||||||
use stdErr = new StreamWriter (stdErrStream)
|
|
||||||
|
|
||||||
use _ = new StdoutSetter (stdOut, stdErr)
|
|
||||||
|
|
||||||
let sw = Stopwatch.StartNew ()
|
let sw = Stopwatch.StartNew ()
|
||||||
|
|
||||||
let metadata () =
|
let metadata () =
|
||||||
@@ -139,13 +129,13 @@ module TestFixture =
|
|||||||
TestName = name
|
TestName = name
|
||||||
ClassName = test.DeclaringType.FullName
|
ClassName = test.DeclaringType.FullName
|
||||||
StdOut =
|
StdOut =
|
||||||
match stdOutStream.ToArray () with
|
match contexts.DumpStdout outputId with
|
||||||
| [||] -> None
|
| "" -> None
|
||||||
| arr -> Console.OutputEncoding.GetString arr |> Some
|
| v -> Some v
|
||||||
StdErr =
|
StdErr =
|
||||||
match stdErrStream.ToArray () with
|
match contexts.DumpStderr outputId with
|
||||||
| [||] -> None
|
| "" -> None
|
||||||
| arr -> Console.OutputEncoding.GetString arr |> Some
|
| v -> Some v
|
||||||
}
|
}
|
||||||
|
|
||||||
let setUpResult = runMethods TestFailure.SetUpFailed setUp [||]
|
let setUpResult = runMethods TestFailure.SetUpFailed setUp [||]
|
||||||
@@ -223,11 +213,15 @@ module TestFixture =
|
|||||||
/// This method should never throw: it only throws if there's a critical logic error in the runner.
|
/// This method should never throw: it only throws if there's a critical logic error in the runner.
|
||||||
/// Exceptions from the units under test are wrapped up and passed out.
|
/// Exceptions from the units under test are wrapped up and passed out.
|
||||||
let private runTestsFromMember
|
let private runTestsFromMember
|
||||||
|
(contexts : TestContexts)
|
||||||
|
(par : ParallelQueue)
|
||||||
|
(running : TestFixtureSetupToken)
|
||||||
|
(progress : ITestProgress)
|
||||||
(setUp : MethodInfo list)
|
(setUp : MethodInfo list)
|
||||||
(tearDown : MethodInfo list)
|
(tearDown : MethodInfo list)
|
||||||
(containingObject : obj)
|
(containingObject : obj)
|
||||||
(test : SingleTestMethod)
|
(test : SingleTestMethod)
|
||||||
: (Result<TestMemberSuccess, TestMemberFailure> * IndividualTestRunMetadata) list
|
: (Result<TestMemberSuccess, TestMemberFailure> * IndividualTestRunMetadata) Task list
|
||||||
=
|
=
|
||||||
if test.Method.ContainsGenericParameters then
|
if test.Method.ContainsGenericParameters then
|
||||||
let failureMetadata =
|
let failureMetadata =
|
||||||
@@ -247,7 +241,7 @@ module TestFixture =
|
|||||||
let error =
|
let error =
|
||||||
TestMemberFailure.Malformed [ "Test contained generic parameters; generics are not supported." ]
|
TestMemberFailure.Malformed [ "Test contained generic parameters; generics are not supported." ]
|
||||||
|
|
||||||
(Error error, failureMetadata) |> List.singleton
|
(Error error, failureMetadata) |> Task.FromResult |> List.singleton
|
||||||
else
|
else
|
||||||
|
|
||||||
let resultPreRun =
|
let resultPreRun =
|
||||||
@@ -263,17 +257,12 @@ module TestFixture =
|
|||||||
| Modifier.Ignored reason -> Some (TestMemberSuccess.Ignored reason)
|
| Modifier.Ignored reason -> Some (TestMemberSuccess.Ignored reason)
|
||||||
)
|
)
|
||||||
|
|
||||||
let sw = Stopwatch.StartNew ()
|
|
||||||
let startTime = DateTimeOffset.Now
|
|
||||||
|
|
||||||
match resultPreRun with
|
match resultPreRun with
|
||||||
| Some result ->
|
| Some result ->
|
||||||
sw.Stop ()
|
|
||||||
|
|
||||||
let failureMetadata =
|
let failureMetadata =
|
||||||
{
|
{
|
||||||
Total = sw.Elapsed
|
Total = TimeSpan.Zero
|
||||||
Start = startTime
|
Start = DateTimeOffset.Now
|
||||||
End = DateTimeOffset.Now
|
End = DateTimeOffset.Now
|
||||||
ComputerName = Environment.MachineName
|
ComputerName = Environment.MachineName
|
||||||
ExecutionId = Guid.NewGuid ()
|
ExecutionId = Guid.NewGuid ()
|
||||||
@@ -285,7 +274,7 @@ module TestFixture =
|
|||||||
StdOut = None
|
StdOut = None
|
||||||
}
|
}
|
||||||
|
|
||||||
[ Ok result, failureMetadata ]
|
(Ok result, failureMetadata) |> Task.FromResult |> List.singleton
|
||||||
| None ->
|
| None ->
|
||||||
|
|
||||||
let individualTests =
|
let individualTests =
|
||||||
@@ -348,7 +337,7 @@ module TestFixture =
|
|||||||
|
|
||||||
// Might not be an IEnumerable of a reference type.
|
// Might not be an IEnumerable of a reference type.
|
||||||
// Concretely, `FSharpList<HttpStatusCode> :> IEnumerable<obj>` fails.
|
// Concretely, `FSharpList<HttpStatusCode> :> IEnumerable<obj>` fails.
|
||||||
for arg in args.GetValue (null : obj) :?> System.Collections.IEnumerable do
|
for arg in args.GetValue (null : obj) :?> IEnumerable do
|
||||||
yield
|
yield
|
||||||
Guid.NewGuid (),
|
Guid.NewGuid (),
|
||||||
match arg with
|
match arg with
|
||||||
@@ -371,20 +360,19 @@ module TestFixture =
|
|||||||
if isNull argsMem then
|
if isNull argsMem then
|
||||||
failwith "Unexpectedly could not call `.Arguments` on TestCaseData"
|
failwith "Unexpectedly could not call `.Arguments` on TestCaseData"
|
||||||
|
|
||||||
|
// TODO: need to capture this stdout/stderr
|
||||||
(argsMem.Invoke (arg, [||]) |> unbox<obj[]>)
|
(argsMem.Invoke (arg, [||]) |> unbox<obj[]>)
|
||||||
else
|
else
|
||||||
[| arg |]
|
[| arg |]
|
||||||
]
|
]
|
||||||
|> Ok
|
|> Ok
|
||||||
|
|
||||||
sw.Stop ()
|
|
||||||
|
|
||||||
match individualTests with
|
match individualTests with
|
||||||
| Error e ->
|
| Error e ->
|
||||||
let failureMetadata =
|
let failureMetadata =
|
||||||
{
|
{
|
||||||
Total = sw.Elapsed
|
Total = TimeSpan.Zero
|
||||||
Start = startTime
|
Start = DateTimeOffset.Now
|
||||||
End = DateTimeOffset.Now
|
End = DateTimeOffset.Now
|
||||||
ComputerName = Environment.MachineName
|
ComputerName = Environment.MachineName
|
||||||
ExecutionId = Guid.NewGuid ()
|
ExecutionId = Guid.NewGuid ()
|
||||||
@@ -397,7 +385,7 @@ module TestFixture =
|
|||||||
StdOut = None
|
StdOut = None
|
||||||
}
|
}
|
||||||
|
|
||||||
[ Error e, failureMetadata ]
|
(Error e, failureMetadata) |> Task.FromResult |> List.singleton
|
||||||
| Ok individualTests ->
|
| Ok individualTests ->
|
||||||
|
|
||||||
let count = test.Repeat |> Option.defaultValue 1
|
let count = test.Repeat |> Option.defaultValue 1
|
||||||
@@ -405,116 +393,205 @@ module TestFixture =
|
|||||||
Seq.init count (fun _ -> individualTests)
|
Seq.init count (fun _ -> individualTests)
|
||||||
|> Seq.concat
|
|> Seq.concat
|
||||||
|> Seq.map (fun (testGuid, args) ->
|
|> Seq.map (fun (testGuid, args) ->
|
||||||
let results, summary =
|
task {
|
||||||
runOne setUp tearDown testGuid test.Method containingObject args
|
let runMe () =
|
||||||
|
progress.OnTestMemberStart test.Name
|
||||||
|
let oldValue = contexts.AsyncLocal.Value
|
||||||
|
let outputId = contexts.NewOutputs ()
|
||||||
|
contexts.AsyncLocal.Value <- outputId
|
||||||
|
|
||||||
match results with
|
let result, meta =
|
||||||
| Ok results -> Ok results, summary
|
runOne outputId contexts setUp tearDown testGuid test.Method containingObject args
|
||||||
| Error e -> Error (TestMemberFailure.Failed e), summary
|
|
||||||
|
contexts.AsyncLocal.Value <- oldValue
|
||||||
|
progress.OnTestMemberFinished test.Name
|
||||||
|
|
||||||
|
result, meta
|
||||||
|
|
||||||
|
let! results, summary = par.Run running test.Parallelize runMe
|
||||||
|
|
||||||
|
match results with
|
||||||
|
| Ok results -> return Ok results, summary
|
||||||
|
| Error e -> return Error (TestMemberFailure.Failed e), summary
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|> Seq.toList
|
|> Seq.toList
|
||||||
|
|
||||||
/// Run every test (except those which fail the `filter`) in this test fixture, as well as the
|
/// Run every test (except those which fail the `filter`) in this test fixture, as well as the
|
||||||
/// appropriate setup and tear-down logic.
|
/// appropriate setup and tear-down logic.
|
||||||
let private runOneFixture
|
let runOneFixture
|
||||||
|
(contexts : TestContexts)
|
||||||
|
(par : ParallelQueue)
|
||||||
(progress : ITestProgress)
|
(progress : ITestProgress)
|
||||||
(filter : TestFixture -> SingleTestMethod -> bool)
|
(filter : TestFixture -> SingleTestMethod -> bool)
|
||||||
(name : string)
|
(name : string)
|
||||||
(containingObject : obj)
|
(containingObject : obj)
|
||||||
(tests : TestFixture)
|
(tests : TestFixture)
|
||||||
: FixtureRunResults
|
: FixtureRunResults Task
|
||||||
=
|
=
|
||||||
progress.OnTestFixtureStart name tests.Tests.Length
|
task {
|
||||||
|
let! running = par.StartTestFixture tests
|
||||||
|
progress.OnTestFixtureStart name tests.Tests.Length
|
||||||
|
|
||||||
let oldWorkDir = Environment.CurrentDirectory
|
let oldWorkDir = Environment.CurrentDirectory
|
||||||
Environment.CurrentDirectory <- FileInfo(tests.ContainingAssembly.Location).Directory.FullName
|
Environment.CurrentDirectory <- FileInfo(tests.ContainingAssembly.Location).Directory.FullName
|
||||||
|
|
||||||
let sw = Stopwatch.StartNew ()
|
let sw = Stopwatch.StartNew ()
|
||||||
let startTime = DateTimeOffset.UtcNow
|
let startTime = DateTimeOffset.UtcNow
|
||||||
|
|
||||||
use stdOutStream = new MemoryStream ()
|
let endMetadata (outputId : OutputStreamId) =
|
||||||
use stdOut = new StreamWriter (stdOutStream)
|
let stdOut = contexts.DumpStdout outputId
|
||||||
use stdErrStream = new MemoryStream ()
|
let stdErr = contexts.DumpStderr outputId
|
||||||
use stdErr = new StreamWriter (stdErrStream)
|
|
||||||
use _ = new StdoutSetter (stdOut, stdErr)
|
|
||||||
|
|
||||||
let endMetadata () =
|
{
|
||||||
let stdOut = stdOutStream.ToArray () |> Console.OutputEncoding.GetString
|
Total = sw.Elapsed
|
||||||
let stdErr = stdErrStream.ToArray () |> Console.OutputEncoding.GetString
|
Start = startTime
|
||||||
|
End = DateTimeOffset.UtcNow
|
||||||
|
ComputerName = Environment.MachineName
|
||||||
|
ExecutionId = Guid.NewGuid ()
|
||||||
|
TestId = Guid.NewGuid ()
|
||||||
|
// This one is a bit dubious, because we don't actually have a test name at all
|
||||||
|
TestName = name
|
||||||
|
ClassName = tests.Name
|
||||||
|
StdOut = if String.IsNullOrEmpty stdOut then None else Some stdOut
|
||||||
|
StdErr = if String.IsNullOrEmpty stdErr then None else Some stdErr
|
||||||
|
}
|
||||||
|
|
||||||
{
|
let! setupResult, running =
|
||||||
Total = sw.Elapsed
|
match tests.OneTimeSetUp with
|
||||||
Start = startTime
|
| Some su ->
|
||||||
End = DateTimeOffset.UtcNow
|
par.RunTestSetup
|
||||||
ComputerName = Environment.MachineName
|
running
|
||||||
ExecutionId = Guid.NewGuid ()
|
(fun () ->
|
||||||
TestId = Guid.NewGuid ()
|
let oldValue = contexts.AsyncLocal.Value
|
||||||
// This one is a bit dubious, because we don't actually have a test name at all
|
let newOutputs = contexts.NewOutputs ()
|
||||||
TestName = name
|
contexts.AsyncLocal.Value <- newOutputs
|
||||||
ClassName = tests.Name
|
|
||||||
StdOut = if String.IsNullOrEmpty stdOut then None else Some stdOut
|
|
||||||
StdErr = if String.IsNullOrEmpty stdErr then None else Some stdErr
|
|
||||||
}
|
|
||||||
|
|
||||||
let setupResult =
|
let result =
|
||||||
match tests.OneTimeSetUp with
|
try
|
||||||
| Some su ->
|
match su.Invoke (containingObject, [||]) with
|
||||||
try
|
| :? unit -> None
|
||||||
match su.Invoke (containingObject, [||]) with
|
| ret ->
|
||||||
| :? unit -> None
|
Some (UserMethodFailure.ReturnedNonUnit (su.Name, ret), endMetadata newOutputs)
|
||||||
| ret -> Some (UserMethodFailure.ReturnedNonUnit (su.Name, ret), endMetadata ())
|
with :? TargetInvocationException as e ->
|
||||||
with :? TargetInvocationException as e ->
|
Some (UserMethodFailure.Threw (su.Name, e.InnerException), endMetadata newOutputs)
|
||||||
Some (UserMethodFailure.Threw (su.Name, e.InnerException), endMetadata ())
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
let testFailures = ResizeArray<TestMemberFailure * IndividualTestRunMetadata> ()
|
contexts.AsyncLocal.Value <- oldValue
|
||||||
|
|
||||||
let successes =
|
match result with
|
||||||
ResizeArray<SingleTestMethod * TestMemberSuccess * IndividualTestRunMetadata> ()
|
| None -> Ok (Some newOutputs)
|
||||||
|
| Some err -> Error (err, newOutputs)
|
||||||
|
)
|
||||||
|
| _ -> Task.FromResult (Ok None, TestFixtureSetupToken.vouchNoSetupRequired running)
|
||||||
|
|
||||||
match setupResult with
|
let testFailures = ResizeArray<TestMemberFailure * IndividualTestRunMetadata> ()
|
||||||
| Some _ ->
|
|
||||||
// Don't run any tests if setup failed.
|
|
||||||
()
|
|
||||||
| None ->
|
|
||||||
for test in tests.Tests do
|
|
||||||
if filter tests test then
|
|
||||||
progress.OnTestMemberStart test.Name
|
|
||||||
let testSuccess = ref 0
|
|
||||||
|
|
||||||
let results = runTestsFromMember tests.SetUp tests.TearDown containingObject test
|
let successes =
|
||||||
|
ResizeArray<SingleTestMethod * TestMemberSuccess * IndividualTestRunMetadata> ()
|
||||||
|
|
||||||
for result, report in results do
|
let testsRun =
|
||||||
match result with
|
match setupResult with
|
||||||
| Error failure ->
|
| Error _ ->
|
||||||
testFailures.Add (failure, report)
|
// Don't run any tests if setup failed.
|
||||||
progress.OnTestFailed test.Name failure
|
Task.FromResult ()
|
||||||
| Ok result ->
|
| Ok _ ->
|
||||||
Interlocked.Increment testSuccess |> ignore<int>
|
tests.Tests
|
||||||
lock successes (fun () -> successes.Add (test, result, report))
|
|> Seq.filter (fun test ->
|
||||||
|
if filter tests test then
|
||||||
|
true
|
||||||
|
else
|
||||||
|
progress.OnTestMemberSkipped test.Name
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|> Seq.map (fun test ->
|
||||||
|
task {
|
||||||
|
let testSuccess = ref 0
|
||||||
|
|
||||||
progress.OnTestMemberFinished test.Name
|
let results =
|
||||||
else
|
runTestsFromMember
|
||||||
progress.OnTestMemberSkipped test.Name
|
contexts
|
||||||
|
par
|
||||||
|
running
|
||||||
|
progress
|
||||||
|
tests.SetUp
|
||||||
|
tests.TearDown
|
||||||
|
containingObject
|
||||||
|
test
|
||||||
|
|
||||||
// Unconditionally run OneTimeTearDown if it exists.
|
let! result =
|
||||||
let tearDownError =
|
results
|
||||||
match tests.OneTimeTearDown with
|
|> List.map (fun t ->
|
||||||
| Some td ->
|
task {
|
||||||
try
|
let! result, report = t
|
||||||
match td.Invoke (containingObject, [||]) with
|
|
||||||
| null -> None
|
|
||||||
| ret -> Some (UserMethodFailure.ReturnedNonUnit (td.Name, ret), endMetadata ())
|
|
||||||
with :? TargetInvocationException as e ->
|
|
||||||
Some (UserMethodFailure.Threw (td.Name, e), endMetadata ())
|
|
||||||
| _ -> None
|
|
||||||
|
|
||||||
Environment.CurrentDirectory <- oldWorkDir
|
match result with
|
||||||
|
| Error failure ->
|
||||||
|
testFailures.Add (failure, report)
|
||||||
|
progress.OnTestFailed test.Name failure
|
||||||
|
| Ok result ->
|
||||||
|
Interlocked.Increment testSuccess |> ignore<int>
|
||||||
|
lock successes (fun () -> successes.Add (test, result, report))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> Task.WhenAll
|
||||||
|
|
||||||
{
|
result |> Array.iter id
|
||||||
Failed = testFailures |> Seq.toList
|
}
|
||||||
Success = successes |> Seq.toList
|
)
|
||||||
OtherFailures = [ tearDownError ; setupResult ] |> List.choose id
|
|> Task.WhenAll
|
||||||
|
|> fun t ->
|
||||||
|
task {
|
||||||
|
let! t = t
|
||||||
|
return t |> Array.iter id
|
||||||
|
}
|
||||||
|
|
||||||
|
do! testsRun
|
||||||
|
|
||||||
|
// Unconditionally run OneTimeTearDown if it exists.
|
||||||
|
let! tearDownError, tornDown =
|
||||||
|
match tests.OneTimeTearDown with
|
||||||
|
| Some td ->
|
||||||
|
par.RunTestTearDown
|
||||||
|
running
|
||||||
|
(fun () ->
|
||||||
|
let oldValue = contexts.AsyncLocal.Value
|
||||||
|
let outputs = contexts.NewOutputs ()
|
||||||
|
contexts.AsyncLocal.Value <- outputs
|
||||||
|
|
||||||
|
let result =
|
||||||
|
try
|
||||||
|
match td.Invoke (containingObject, [||]) with
|
||||||
|
| :? unit -> None
|
||||||
|
| ret ->
|
||||||
|
Some (UserMethodFailure.ReturnedNonUnit (td.Name, ret), endMetadata outputs)
|
||||||
|
with :? TargetInvocationException as e ->
|
||||||
|
Some (UserMethodFailure.Threw (td.Name, e.InnerException), endMetadata outputs)
|
||||||
|
|
||||||
|
contexts.AsyncLocal.Value <- oldValue
|
||||||
|
|
||||||
|
match result with
|
||||||
|
| None -> Ok (Some outputs)
|
||||||
|
| Some err -> Error (err, outputs)
|
||||||
|
)
|
||||||
|
| _ -> Task.FromResult (Ok None, TestFixtureTearDownToken.vouchNoTearDownRequired running)
|
||||||
|
|
||||||
|
Environment.CurrentDirectory <- oldWorkDir
|
||||||
|
|
||||||
|
do! par.EndTestFixture tornDown
|
||||||
|
|
||||||
|
// TODO: we have access to stdout/err of OneTimeSetUp and OneTimeTearDown here, but we throw them away.
|
||||||
|
return
|
||||||
|
{
|
||||||
|
Failed = testFailures |> Seq.toList
|
||||||
|
Success = successes |> Seq.toList
|
||||||
|
OtherFailures =
|
||||||
|
[ tearDownError ; setupResult ]
|
||||||
|
|> List.choose (
|
||||||
|
function
|
||||||
|
| Error (e, _) -> Some e
|
||||||
|
| Ok _ -> None
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interpret this type as a [<TestFixture>], extracting the test members from it and annotating them with all
|
/// Interpret this type as a [<TestFixture>], extracting the test members from it and annotating them with all
|
||||||
@@ -550,14 +627,16 @@ module TestFixture =
|
|||||||
| [ v ] ->
|
| [ v ] ->
|
||||||
match v.Value with
|
match v.Value with
|
||||||
| :? int as v ->
|
| :? int as v ->
|
||||||
match v with
|
match ParallelScope.ofInt v with
|
||||||
| 512 -> categories, args, Some (Parallelizable.Yes ClassParallelScope.Fixtures)
|
| ParallelScope.Fixtures ->
|
||||||
| 256 -> categories, args, Some (Parallelizable.Yes ClassParallelScope.Children)
|
categories, args, Some (Parallelizable.Yes ClassParallelScope.Fixtures)
|
||||||
| 257 -> categories, args, Some (Parallelizable.Yes ClassParallelScope.All)
|
| ParallelScope.Children ->
|
||||||
| 1 -> categories, args, Some (Parallelizable.Yes ClassParallelScope.Self)
|
categories, args, Some (Parallelizable.Yes ClassParallelScope.Children)
|
||||||
| v ->
|
| ParallelScope.All ->
|
||||||
failwith
|
categories, args, Some (Parallelizable.Yes ClassParallelScope.All)
|
||||||
$"Could not recognise value %i{v} of parallel scope in %s{parentType.FullName}"
|
| ParallelScope.Self ->
|
||||||
|
categories, args, Some (Parallelizable.Yes ClassParallelScope.Self)
|
||||||
|
| ParallelScope.None -> categories, args, Some Parallelizable.No
|
||||||
| v ->
|
| v ->
|
||||||
failwith
|
failwith
|
||||||
$"Unexpectedly non-int value %O{v} of parallel scope in %s{parentType.FullName}"
|
$"Unexpectedly non-int value %O{v} of parallel scope in %s{parentType.FullName}"
|
||||||
@@ -639,10 +718,12 @@ module TestFixture =
|
|||||||
/// Run every test (except those which fail the `filter`) in this test fixture, as well as the
|
/// Run every test (except those which fail the `filter`) in this test fixture, as well as the
|
||||||
/// appropriate setup and tear-down logic.
|
/// appropriate setup and tear-down logic.
|
||||||
let run
|
let run
|
||||||
|
(contexts : TestContexts)
|
||||||
|
(par : ParallelQueue)
|
||||||
(progress : ITestProgress)
|
(progress : ITestProgress)
|
||||||
(filter : TestFixture -> SingleTestMethod -> bool)
|
(filter : TestFixture -> SingleTestMethod -> bool)
|
||||||
(tests : TestFixture)
|
(tests : TestFixture)
|
||||||
: FixtureRunResults list
|
: FixtureRunResults list Task
|
||||||
=
|
=
|
||||||
match tests.Parameters with
|
match tests.Parameters with
|
||||||
| [] -> [ null ]
|
| [] -> [ null ]
|
||||||
@@ -678,5 +759,11 @@ module TestFixture =
|
|||||||
let args = args |> Seq.map (fun o -> o.ToString ()) |> String.concat ","
|
let args = args |> Seq.map (fun o -> o.ToString ()) |> String.concat ","
|
||||||
$"%s{tests.Name}(%s{args})"
|
$"%s{tests.Name}(%s{args})"
|
||||||
|
|
||||||
runOneFixture progress filter name containingObject tests
|
runOneFixture contexts par progress filter name containingObject tests
|
||||||
)
|
)
|
||||||
|
|> Task.WhenAll
|
||||||
|
|> fun t ->
|
||||||
|
task {
|
||||||
|
let! t = t
|
||||||
|
return Array.toList t
|
||||||
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
namespace WoofWare.NUnitTestRunner
|
namespace WoofWare.NUnitTestRunner
|
||||||
|
|
||||||
open System
|
open System
|
||||||
|
open System.IO
|
||||||
|
|
||||||
/// Represents something which knows how to report progress through a test suite.
|
/// Represents something which knows how to report progress through a test suite.
|
||||||
/// Note that we don't guarantee anything about parallelism; you must make sure
|
/// Note that we don't guarantee anything about parallelism; you must make sure
|
||||||
@@ -24,22 +25,25 @@ type ITestProgress =
|
|||||||
/// Methods for constructing specific ITestProgress objects.
|
/// Methods for constructing specific ITestProgress objects.
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module TestProgress =
|
module TestProgress =
|
||||||
/// An ITestProgress which logs to stderr.
|
/// An ITestProgress which logs to the given writer.
|
||||||
let toStderr () : ITestProgress =
|
let toWriter (writer : TextWriter) : ITestProgress =
|
||||||
{ new ITestProgress with
|
{ new ITestProgress with
|
||||||
member _.OnTestFixtureStart name testCount =
|
member _.OnTestFixtureStart name testCount =
|
||||||
let plural = if testCount = 1 then "" else "s"
|
let plural = if testCount = 1 then "" else "s"
|
||||||
Console.Error.WriteLine $"Running test fixture: %s{name} (%i{testCount} test%s{plural} to run)"
|
writer.WriteLine $"Running test fixture: %s{name} (%i{testCount} test%s{plural} to run)"
|
||||||
|
|
||||||
member _.OnTestMemberStart name =
|
member _.OnTestMemberStart name =
|
||||||
Console.Error.WriteLine $"Running test: %s{name}"
|
writer.WriteLine $"Running test: %s{name}"
|
||||||
|
|
||||||
member _.OnTestFailed name failure =
|
member _.OnTestFailed name failure =
|
||||||
Console.Error.WriteLine $"Test failed: %O{failure}"
|
writer.WriteLine $"Test failed: %O{failure}"
|
||||||
|
|
||||||
member _.OnTestMemberFinished name =
|
member _.OnTestMemberFinished name =
|
||||||
Console.Error.WriteLine $"Finished test %s{name}"
|
writer.WriteLine $"Finished test %s{name}"
|
||||||
|
|
||||||
member _.OnTestMemberSkipped name =
|
member _.OnTestMemberSkipped name =
|
||||||
Console.Error.WriteLine $"Skipping test due to filter: %s{name}"
|
writer.WriteLine $"Skipping test due to filter: %s{name}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An ITestProgress which logs to stderr.
|
||||||
|
let toStderr () : ITestProgress = toWriter Console.Error
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
<PackageId>WoofWare.NUnitTestRunner.Lib</PackageId>
|
<PackageId>WoofWare.NUnitTestRunner.Lib</PackageId>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<WarnOn>FS3559</WarnOn>
|
<WarnOn>FS3559</WarnOn>
|
||||||
<WoofWareMyriadPluginVersion>2.1.44</WoofWareMyriadPluginVersion>
|
<WoofWareMyriadPluginVersion>4.0.9</WoofWareMyriadPluginVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -23,17 +23,23 @@
|
|||||||
<Compile Include="GeneratedRuntimeConfig.fs">
|
<Compile Include="GeneratedRuntimeConfig.fs">
|
||||||
<MyriadFile>RuntimeConfig.fs</MyriadFile>
|
<MyriadFile>RuntimeConfig.fs</MyriadFile>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="ParallelScope.fs" />
|
||||||
<Compile Include="DotnetRuntime.fs" />
|
<Compile Include="DotnetRuntime.fs" />
|
||||||
<Compile Include="Array.fs" />
|
<Compile Include="Array.fs" />
|
||||||
<Compile Include="List.fs" />
|
<Compile Include="List.fs" />
|
||||||
<Compile Include="Result.fs" />
|
<Compile Include="Result.fs" />
|
||||||
<Compile Include="Domain.fs" />
|
<Compile Include="Domain.fs" />
|
||||||
<Compile Include="Filter.fs" />
|
<Compile Include="Filter.fs" />
|
||||||
|
<Compile Include="Args.fs" />
|
||||||
|
<Compile Include="ParallelQueue.fs" />
|
||||||
<Compile Include="SingleTestMethod.fs" />
|
<Compile Include="SingleTestMethod.fs" />
|
||||||
<Compile Include="TestProgress.fs" />
|
<Compile Include="TestProgress.fs" />
|
||||||
|
<Compile Include="Context.fs" />
|
||||||
<Compile Include="TestFixture.fs" />
|
<Compile Include="TestFixture.fs" />
|
||||||
<Compile Include="Xml.fs" />
|
<Compile Include="Xml.fs" />
|
||||||
<Compile Include="TrxReport.fs" />
|
<Compile Include="TrxReport.fs" />
|
||||||
|
<Compile Include="CreateTrxReport.fs" />
|
||||||
|
<Compile Include="AssemblyLevelAttributes.fs" />
|
||||||
<None Include="..\README.md">
|
<None Include="..\README.md">
|
||||||
<Pack>True</Pack>
|
<Pack>True</Pack>
|
||||||
<PackagePath>\</PackagePath>
|
<PackagePath>\</PackagePath>
|
||||||
@@ -42,14 +48,14 @@
|
|||||||
<EmbeddedResource Include="version.json" />
|
<EmbeddedResource Include="version.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="WoofWare.PrattParser" Version="0.1.2" />
|
<PackageReference Include="WoofWare.PrattParser" Version="0.2.3" />
|
||||||
<PackageReference Update="FSharp.Core" Version="6.0.0" />
|
<PackageReference Update="FSharp.Core" Version="6.0.1" />
|
||||||
<PackageReference Include="WoofWare.DotnetRuntimeLocator" Version="0.1.4" />
|
<PackageReference Include="WoofWare.DotnetRuntimeLocator" Version="0.1.11" />
|
||||||
<PackageReference Include="WoofWare.Myriad.Plugins.Attributes" Version="3.1.6" />
|
<PackageReference Include="WoofWare.Myriad.Plugins.Attributes" Version="3.6.6" />
|
||||||
<PackageReference Include="Myriad.SDK" Version="0.8.3" />
|
<PackageReference Include="Myriad.SDK" Version="0.8.3" PrivateAssets="all" />
|
||||||
<PackageReference Include="WoofWare.Myriad.Plugins" Version="$(WoofWareMyriadPluginVersion)" PrivateAssets="all" />
|
<PackageReference Include="WoofWare.Myriad.Plugins" Version="$(WoofWareMyriadPluginVersion)" PrivateAssets="all" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<MyriadSdkGenerator Include="$(NuGetPackageRoot)/woofware.myriad.plugins/$(WoofWareMyriadPluginVersion)/lib/net6.0/WoofWare.Myriad.Plugins.dll" />
|
<MyriadSdkGenerator Include="$(NuGetPackageRoot)/woofware.myriad.plugins/$(WoofWareMyriadPluginVersion)/lib/net6.0/WoofWare.Myriad.Plugins.dll" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "0.12",
|
"version": "0.20",
|
||||||
"publicReleaseRefSpec": [
|
"publicReleaseRefSpec": [
|
||||||
"^refs/heads/main$"
|
"^refs/heads/main$"
|
||||||
],
|
],
|
||||||
|
35
WoofWare.NUnitTestRunner.StartupHook/StartupHook.cs
Normal file
35
WoofWare.NUnitTestRunner.StartupHook/StartupHook.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
using WoofWare.NUnitTestRunner.StartupHook;
|
||||||
|
|
||||||
|
namespace WoofWare.NUnitTestRunner.StartupHook
|
||||||
|
{
|
||||||
|
internal class StartupAssemblyLoadContext : AssemblyLoadContext
|
||||||
|
{
|
||||||
|
private readonly AssemblyDependencyResolver _resolver;
|
||||||
|
|
||||||
|
public StartupAssemblyLoadContext()
|
||||||
|
{
|
||||||
|
_resolver = new AssemblyDependencyResolver(Assembly.GetExecutingAssembly().Location);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Assembly Load(AssemblyName assemblyName)
|
||||||
|
{
|
||||||
|
var assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
|
||||||
|
|
||||||
|
return assemblyPath != null ? LoadFromAssemblyPath(assemblyPath) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be internal and called `StartupHook`
|
||||||
|
internal class StartupHook
|
||||||
|
{
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
var loadContext = new StartupAssemblyLoadContext();
|
||||||
|
var assembly = loadContext.LoadFromAssemblyName(new AssemblyName("WoofWare.NUnitTestRunner.StartupHookLogic"));
|
||||||
|
assembly.DefinedTypes.First(x => x.Name == "StartupHookLogic").GetDeclaredMethod("DoIt")!.Invoke(null, null);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\WoofWare.NUnitTestRunner.StartupHookLogic\WoofWare.NUnitTestRunner.StartupHookLogic.csproj" />
|
||||||
|
<ProjectReference Include="..\WoofWare.NUnitTestRunner.Lib\WoofWare.NUnitTestRunner.Lib.fsproj"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="StartupHook.cs"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
102
WoofWare.NUnitTestRunner.StartupHookLogic/StartupHookLogic.cs
Normal file
102
WoofWare.NUnitTestRunner.StartupHookLogic/StartupHookLogic.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.FSharp.Collections;
|
||||||
|
using Microsoft.FSharp.Core;
|
||||||
|
|
||||||
|
namespace WoofWare.NUnitTestRunner.StartupHookLogic;
|
||||||
|
|
||||||
|
public class StartupHookLogic
|
||||||
|
{
|
||||||
|
private static void DoIt()
|
||||||
|
{
|
||||||
|
// Load test runner lib
|
||||||
|
var nunitLib = Environment.GetEnvironmentVariable("WOOFWARE_NUNIT_LIB");
|
||||||
|
if (string.IsNullOrEmpty(nunitLib))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("WoofWare.NUnitTestRunner hook expects to run with WOOFWARE_NUNIT_LIB set to WoofWare.NUnitTestRunner.Lib.dll");
|
||||||
|
}
|
||||||
|
Assembly.LoadFrom(nunitLib);
|
||||||
|
|
||||||
|
var startTime = DateTimeOffset.Now;
|
||||||
|
|
||||||
|
// Arg parsing
|
||||||
|
|
||||||
|
var filterVar = Environment.GetEnvironmentVariable("WOOFWARE_NUNIT_FILTER");
|
||||||
|
static bool NoFilter(TestFixture f, SingleTestMethod g)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSharpFunc<TestFixture, FSharpFunc<SingleTestMethod, bool>> filter;
|
||||||
|
if (string.IsNullOrEmpty(filterVar))
|
||||||
|
{
|
||||||
|
filter = FuncConvert.FromFunc<TestFixture, SingleTestMethod, bool>(NoFilter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filter = FilterModule.shouldRun(FilterModule.parse(filterVar));
|
||||||
|
}
|
||||||
|
|
||||||
|
var assy = Assembly.GetEntryAssembly()!;
|
||||||
|
|
||||||
|
var attrs = AssemblyLevelAttributesModule.get(assy);
|
||||||
|
|
||||||
|
FSharpOption<int> levelOfParallelism;
|
||||||
|
var parallelismVar = Environment.GetEnvironmentVariable("WOOFWARE_NUNIT_PARALLELISM_LEVEL");
|
||||||
|
if (string.IsNullOrEmpty(parallelismVar))
|
||||||
|
{
|
||||||
|
levelOfParallelism = attrs.Parallelism;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
levelOfParallelism = FSharpOption<int>.Some(Int32.Parse(parallelismVar));
|
||||||
|
}
|
||||||
|
|
||||||
|
var testFixtures = assy.ExportedTypes.Select(TestFixtureModule.parse);
|
||||||
|
using var par =
|
||||||
|
new ParallelQueue(levelOfParallelism, attrs.Parallelizable, FSharpOption<CancellationToken>.None);
|
||||||
|
var creationTime = DateTimeOffset.Now;
|
||||||
|
|
||||||
|
var timeoutVar = Environment.GetEnvironmentVariable("WOOFWARE_NUNIT_TIMEOUT_SECS");
|
||||||
|
TimeSpan timeout;
|
||||||
|
if (string.IsNullOrEmpty(timeoutVar))
|
||||||
|
{
|
||||||
|
timeout = TimeSpan.FromHours(2.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeout = TimeSpan.FromSeconds(Int32.Parse(timeoutVar));
|
||||||
|
}
|
||||||
|
|
||||||
|
var normalErr = Console.Error;
|
||||||
|
using var contexts = TestContexts.Empty();
|
||||||
|
Console.SetOut(contexts.Stdout);
|
||||||
|
Console.SetError(contexts.Stderr);
|
||||||
|
var results =
|
||||||
|
Task.WhenAll(testFixtures.Select(x =>
|
||||||
|
TestFixtureModule.run(contexts, par, TestProgress.toWriter(normalErr), filter, x)));
|
||||||
|
|
||||||
|
if (!results.Wait(timeout))
|
||||||
|
{
|
||||||
|
throw new Exception($"Tests failed to terminate within timeout of {timeout}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var sorted =
|
||||||
|
results.Result.SelectMany(x => x);
|
||||||
|
var report = BuildTrxReport.build(assy, creationTime, startTime, ListModule.OfSeq(sorted));
|
||||||
|
|
||||||
|
var trxFile = Environment.GetEnvironmentVariable("WOOFWARE_NUNIT_GENERATE_TRX");
|
||||||
|
if (!string.IsNullOrEmpty(trxFile))
|
||||||
|
{
|
||||||
|
var contents = TrxReportModule.toXml(report).OuterXml;
|
||||||
|
var trxPath = new FileInfo(trxFile);
|
||||||
|
trxPath.Directory!.Create();
|
||||||
|
File.WriteAllText(trxPath.FullName, contents);
|
||||||
|
normalErr.WriteLine($"Written TRX file: {trxPath.FullName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (report.ResultsSummary.Outcome.Equals(TrxOutcome.Completed))
|
||||||
|
Environment.Exit(0);
|
||||||
|
else
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\WoofWare.NUnitTestRunner.Lib\WoofWare.NUnitTestRunner.Lib.fsproj"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="StartupHookLogic.cs"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@@ -8,6 +8,12 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "WoofWare.NUnitTestRunner.Li
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "WoofWare.NUnitTestRunner.Test", "WoofWare.NUnitTestRunner\WoofWare.NUnitTestRunner.Test\WoofWare.NUnitTestRunner.Test.fsproj", "{443B01B3-2A8C-45CF-96D6-1D890EEA0533}"
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "WoofWare.NUnitTestRunner.Test", "WoofWare.NUnitTestRunner\WoofWare.NUnitTestRunner.Test\WoofWare.NUnitTestRunner.Test.fsproj", "{443B01B3-2A8C-45CF-96D6-1D890EEA0533}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WoofWare.NUnitTestRunner.StartupHook", "WoofWare.NUnitTestRunner.StartupHook\WoofWare.NUnitTestRunner.StartupHook.csproj", "{E2C73D96-570C-4E3C-B997-707AF8BB0E6A}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WoofWare.NUnitTestRunner.StartupHookLogic", "WoofWare.NUnitTestRunner.StartupHookLogic\WoofWare.NUnitTestRunner.StartupHookLogic.csproj", "{A70627C8-9D19-42C2-AFEB-CFBDDDCE045D}"
|
||||||
|
EndProject
|
||||||
|
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FailingConsumer", "FailingConsumer\FailingConsumer.fsproj", "{DA7160F5-4C3C-4D2E-918B-7DCBA3F4272E}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -30,5 +36,17 @@ Global
|
|||||||
{443B01B3-2A8C-45CF-96D6-1D890EEA0533}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{443B01B3-2A8C-45CF-96D6-1D890EEA0533}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{443B01B3-2A8C-45CF-96D6-1D890EEA0533}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{443B01B3-2A8C-45CF-96D6-1D890EEA0533}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{443B01B3-2A8C-45CF-96D6-1D890EEA0533}.Release|Any CPU.Build.0 = Release|Any CPU
|
{443B01B3-2A8C-45CF-96D6-1D890EEA0533}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E2C73D96-570C-4E3C-B997-707AF8BB0E6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E2C73D96-570C-4E3C-B997-707AF8BB0E6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E2C73D96-570C-4E3C-B997-707AF8BB0E6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E2C73D96-570C-4E3C-B997-707AF8BB0E6A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A70627C8-9D19-42C2-AFEB-CFBDDDCE045D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A70627C8-9D19-42C2-AFEB-CFBDDDCE045D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A70627C8-9D19-42C2-AFEB-CFBDDDCE045D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A70627C8-9D19-42C2-AFEB-CFBDDDCE045D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DA7160F5-4C3C-4D2E-918B-7DCBA3F4272E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DA7160F5-4C3C-4D2E-918B-7DCBA3F4272E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DA7160F5-4C3C-4D2E-918B-7DCBA3F4272E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DA7160F5-4C3C-4D2E-918B-7DCBA3F4272E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@@ -1,346 +1,84 @@
|
|||||||
namespace WoofWare.NUnitTestRunner
|
namespace WoofWare.NUnitTestRunner
|
||||||
|
|
||||||
open System
|
open System
|
||||||
|
open System.Diagnostics
|
||||||
open System.IO
|
open System.IO
|
||||||
open System.Reflection
|
open System.Reflection
|
||||||
open System.Runtime.Loader
|
open System.Threading.Tasks
|
||||||
|
open Spectre.Console
|
||||||
// Fix for https://github.com/Smaug123/unofficial-nunit-runner/issues/8
|
|
||||||
// Set AppContext.BaseDirectory to where the test DLL is.
|
|
||||||
// (This tells the DLL loader to look next to the test DLL for dependencies.)
|
|
||||||
type SetBaseDir (testDll : FileInfo) =
|
|
||||||
let oldBaseDir = AppContext.BaseDirectory
|
|
||||||
do AppContext.SetData ("APP_CONTEXT_BASE_DIRECTORY", testDll.Directory.FullName)
|
|
||||||
|
|
||||||
interface IDisposable with
|
|
||||||
member _.Dispose () =
|
|
||||||
AppContext.SetData ("APP_CONTEXT_BASE_DIRECTORY", oldBaseDir)
|
|
||||||
|
|
||||||
|
|
||||||
type Ctx (dll : FileInfo, runtimes : DirectoryInfo list) =
|
|
||||||
inherit AssemblyLoadContext ()
|
|
||||||
|
|
||||||
override this.Load (target : AssemblyName) : Assembly =
|
|
||||||
let path = Path.Combine (dll.Directory.FullName, $"%s{target.Name}.dll")
|
|
||||||
|
|
||||||
if File.Exists path then
|
|
||||||
this.LoadFromAssemblyPath path
|
|
||||||
else
|
|
||||||
|
|
||||||
runtimes
|
|
||||||
|> List.tryPick (fun di ->
|
|
||||||
let path = Path.Combine (di.FullName, $"%s{target.Name}.dll")
|
|
||||||
|
|
||||||
if File.Exists path then
|
|
||||||
this.LoadFromAssemblyPath path |> Some
|
|
||||||
else
|
|
||||||
None
|
|
||||||
)
|
|
||||||
|> Option.defaultValue null
|
|
||||||
|
|
||||||
|
|
||||||
module Program =
|
module Program =
|
||||||
let main argv =
|
// This is actually transcribed into C# in WoofWare.NUnitTestRunner.StartupHookLogic.
|
||||||
|
let execute argv =
|
||||||
let startTime = DateTimeOffset.Now
|
let startTime = DateTimeOffset.Now
|
||||||
|
|
||||||
let testDll, filter, trxPath =
|
let args = argv |> List.ofArray |> Args.Parse
|
||||||
match argv |> List.ofSeq with
|
|
||||||
| [ dll ] -> FileInfo dll, None, None
|
|
||||||
| [ dll ; "--trx" ; trxPath ] -> FileInfo dll, None, Some (FileInfo trxPath)
|
|
||||||
| [ dll ; "--filter" ; filter ] -> FileInfo dll, Some (Filter.parse filter), None
|
|
||||||
| [ dll ; "--trx" ; trxPath ; "--filter" ; filter ] ->
|
|
||||||
FileInfo dll, Some (Filter.parse filter), Some (FileInfo trxPath)
|
|
||||||
| [ dll ; "--filter" ; filter ; "--trx" ; trxPath ] ->
|
|
||||||
FileInfo dll, Some (Filter.parse filter), Some (FileInfo trxPath)
|
|
||||||
| _ ->
|
|
||||||
failwith
|
|
||||||
"provide exactly one arg, a test DLL; then optionally `--filter <filter>` and/or `--trx <output-filename>`."
|
|
||||||
|
|
||||||
let filter =
|
let filter =
|
||||||
match filter with
|
match args.Filter with
|
||||||
| Some filter -> Filter.shouldRun filter
|
| Some (_, filter) -> Filter.shouldRun filter
|
||||||
| None -> fun _ _ -> true
|
| None -> fun _ _ -> true
|
||||||
|
|
||||||
let progress = Progress.spectre ()
|
let stderr =
|
||||||
|
let consoleSettings = AnsiConsoleSettings ()
|
||||||
|
consoleSettings.Out <- AnsiConsoleOutput Console.Error
|
||||||
|
AnsiConsole.Create consoleSettings
|
||||||
|
|
||||||
use _ = new SetBaseDir (testDll)
|
let progress = Progress.spectre stderr
|
||||||
|
|
||||||
let ctx = Ctx (testDll, DotnetRuntime.locate testDll)
|
let runtime = DotnetRuntime.locate args.Dll
|
||||||
let assy = ctx.LoadFromAssemblyPath testDll.FullName
|
|
||||||
|
|
||||||
let levelOfParallelism, par =
|
match args.Logging with
|
||||||
((None, None), assy.CustomAttributes)
|
| LogLevel.Nothing -> ()
|
||||||
||> Seq.fold (fun (levelPar, par) attr ->
|
| LogLevel.Verbose ->
|
||||||
match attr.AttributeType.FullName with
|
for d in runtime do
|
||||||
| "NUnit.Framework.LevelOfParallelismAttribute" ->
|
stderr.WriteLine $".NET runtime directory: %s{d.FullName}"
|
||||||
let arg = attr.ConstructorArguments |> Seq.exactlyOne |> _.Value |> unbox<int>
|
|
||||||
|
|
||||||
match levelPar with
|
use contexts = TestContexts.Empty ()
|
||||||
| None -> (Some arg, par)
|
|
||||||
| Some existing ->
|
let ctx = LoadContext (args.Dll, runtime, contexts)
|
||||||
failwith $"Assembly %s{assy.Location} declares parallelism %i{arg} and also %i{existing}"
|
let assy = ctx.LoadFromAssemblyPath args.Dll.FullName
|
||||||
| "NUnit.Framework.NonParallelizableAttribute" ->
|
|
||||||
match levelPar with
|
let attrs = AssemblyLevelAttributes.get assy
|
||||||
| None -> (Some 1, par)
|
|
||||||
| Some existing ->
|
let levelOfParallelism =
|
||||||
failwith
|
match args.LevelOfParallelism, attrs.Parallelism with
|
||||||
$"Assembly %s{assy.Location} declares non-parallelizable and also parallelism %i{existing}"
|
| None, None -> None
|
||||||
| "NUnit.Framework.ParallelizableAttribute" ->
|
| Some taken, Some ignored ->
|
||||||
match par with
|
match args.Logging with
|
||||||
| Some _ -> failwith "Got multiple Parallelize attributes in assembly"
|
| LogLevel.Nothing -> ()
|
||||||
| None ->
|
| LogLevel.Verbose ->
|
||||||
match attr.ConstructorArguments |> Seq.toList with
|
stderr.WriteLine
|
||||||
| [] -> levelPar, Some (Parallelizable.Yes AssemblyParallelScope.Fixtures)
|
$"Taking parallelism %i{taken} from command line, ignoring value %i{ignored} from assembly"
|
||||||
| [ v ] ->
|
|
||||||
match v.Value with
|
Some taken
|
||||||
| :? int as v ->
|
| Some x, None
|
||||||
match v with
|
| None, Some x -> Some x
|
||||||
| 512 -> levelPar, Some (Parallelizable.Yes AssemblyParallelScope.Fixtures)
|
|
||||||
| 256 -> levelPar, Some (Parallelizable.Yes AssemblyParallelScope.Children)
|
|
||||||
| 257 ->
|
|
||||||
failwith "ParallelScope.All is invalid on assemblies; only Fixtures or Children"
|
|
||||||
| 1 ->
|
|
||||||
failwith "ParallelScope.Self is invalid on assemblies; only Fixtures or Children"
|
|
||||||
| v -> failwith $"Could not recognise value %i{v} of parallel scope on assembly"
|
|
||||||
| v -> failwith $"Unexpectedly non-int value %O{v} of parallel scope on assembly"
|
|
||||||
| _ -> failwith "unexpectedly got multiple args to Parallelizable on assembly"
|
|
||||||
| _ -> levelPar, par
|
|
||||||
)
|
|
||||||
|
|
||||||
let testFixtures = assy.ExportedTypes |> Seq.map TestFixture.parse |> Seq.toList
|
let testFixtures = assy.ExportedTypes |> Seq.map TestFixture.parse |> Seq.toList
|
||||||
|
|
||||||
|
use par = new ParallelQueue (levelOfParallelism, attrs.Parallelizable)
|
||||||
|
|
||||||
let creationTime = DateTimeOffset.Now
|
let creationTime = DateTimeOffset.Now
|
||||||
let results = testFixtures |> List.collect (TestFixture.run progress filter)
|
|
||||||
|
|
||||||
let finishTime = DateTimeOffset.Now
|
|
||||||
let finishTimeHumanReadable = finishTime.ToString @"yyyy-MM-dd HH:mm:ss"
|
|
||||||
let nowMachine = finishTime.ToString @"yyyy-MM-dd_HH_mm_ss"
|
|
||||||
|
|
||||||
let testListId = Guid.NewGuid ()
|
|
||||||
|
|
||||||
let testDefinitions, testEntries =
|
|
||||||
results
|
|
||||||
|> List.collect (fun results -> results.IndividualTestRunMetadata)
|
|
||||||
|> List.map (fun (data, _) ->
|
|
||||||
let defn =
|
|
||||||
{
|
|
||||||
Name = data.TestName
|
|
||||||
Storage = assy.Location.ToLowerInvariant ()
|
|
||||||
Id = data.TestId
|
|
||||||
Execution =
|
|
||||||
{
|
|
||||||
Id = data.ExecutionId
|
|
||||||
}
|
|
||||||
TestMethod =
|
|
||||||
{
|
|
||||||
CodeBase = assy.Location
|
|
||||||
AdapterTypeName = Uri "executor://woofware/"
|
|
||||||
ClassName = data.ClassName
|
|
||||||
Name = data.TestName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let entry : TrxTestEntry =
|
|
||||||
{
|
|
||||||
TestListId = testListId
|
|
||||||
ExecutionId = data.ExecutionId
|
|
||||||
TestId = data.TestId
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
defn, entry
|
|
||||||
)
|
|
||||||
|> List.unzip
|
|
||||||
|
|
||||||
let hostname = Environment.MachineName
|
|
||||||
|
|
||||||
let settings =
|
|
||||||
{
|
|
||||||
Name = "default"
|
|
||||||
Id = Guid.NewGuid ()
|
|
||||||
Deployment =
|
|
||||||
{
|
|
||||||
RunDeploymentRoot = $"_%s{hostname}_%s{nowMachine}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let testList : TrxTestListEntry =
|
|
||||||
{
|
|
||||||
Id = testListId
|
|
||||||
Name = "All"
|
|
||||||
}
|
|
||||||
|
|
||||||
let counters =
|
|
||||||
(TrxCounters.Zero, results)
|
|
||||||
// TODO: this is woefully inefficient
|
|
||||||
||> List.fold (fun counters results ->
|
|
||||||
let counters =
|
|
||||||
(counters, results.Failed)
|
|
||||||
||> List.fold (fun counters (_, _) ->
|
|
||||||
// TODO: the counters can be more specific about the failure mode
|
|
||||||
counters.AddFailed ()
|
|
||||||
)
|
|
||||||
|
|
||||||
let counters =
|
|
||||||
(counters, results.OtherFailures)
|
|
||||||
||> List.fold (fun counters _ ->
|
|
||||||
// TODO: the counters can be more specific about the failure mode
|
|
||||||
counters.AddFailed ()
|
|
||||||
)
|
|
||||||
|
|
||||||
(counters, results.Success)
|
|
||||||
||> List.fold (fun counters (_, success, _) ->
|
|
||||||
match success with
|
|
||||||
| TestMemberSuccess.Ok -> counters.AddPassed ()
|
|
||||||
| TestMemberSuccess.Ignored _
|
|
||||||
| TestMemberSuccess.Explicit _ -> counters.AddNotExecuted ()
|
|
||||||
| TestMemberSuccess.Inconclusive _ -> counters.AddInconclusive ()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: I'm sure we can do better than this; there's a whole range of possible
|
|
||||||
// states!
|
|
||||||
let outcome =
|
|
||||||
if counters.Failed > 0u then
|
|
||||||
TrxOutcome.Failed
|
|
||||||
else
|
|
||||||
TrxOutcome.Completed
|
|
||||||
|
|
||||||
let resultSummary : TrxResultsSummary =
|
|
||||||
{
|
|
||||||
Outcome = outcome
|
|
||||||
Counters = counters
|
|
||||||
Output =
|
|
||||||
{
|
|
||||||
StdOut = None
|
|
||||||
StdErr = None
|
|
||||||
ErrorInfo = None
|
|
||||||
}
|
|
||||||
RunInfos =
|
|
||||||
[
|
|
||||||
// TODO: capture stdout
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
let times : TrxReportTimes =
|
|
||||||
{
|
|
||||||
Creation = creationTime
|
|
||||||
Queuing = startTime
|
|
||||||
Start = startTime
|
|
||||||
Finish = finishTime
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
let magicGuid = Guid.Parse "13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b"
|
|
||||||
|
|
||||||
let results =
|
let results =
|
||||||
results
|
testFixtures
|
||||||
|> List.collect (fun results -> results.IndividualTestRunMetadata)
|
|> List.map (TestFixture.run contexts par progress filter)
|
||||||
|> List.map (fun (i, cause) ->
|
|> Task.WhenAll
|
||||||
let exc =
|
|
||||||
match cause with
|
|
||||||
| Choice2Of3 _ -> None
|
|
||||||
| Choice1Of3 (TestMemberFailure.Malformed reasons) ->
|
|
||||||
{
|
|
||||||
StackTrace = None
|
|
||||||
Message = reasons |> String.concat "\n" |> Some
|
|
||||||
}
|
|
||||||
|> Some
|
|
||||||
| Choice1Of3 (TestMemberFailure.Failed fail)
|
|
||||||
| Choice1Of3 (TestMemberFailure.Failed fail)
|
|
||||||
| Choice1Of3 (TestMemberFailure.Failed fail) ->
|
|
||||||
((None, None), fail)
|
|
||||||
||> List.fold (fun (stackTrace, message) tf ->
|
|
||||||
match tf with
|
|
||||||
| TestFailure.TestFailed (UserMethodFailure.Threw (_, exc))
|
|
||||||
| TestFailure.SetUpFailed (UserMethodFailure.Threw (_, exc))
|
|
||||||
| TestFailure.TearDownFailed (UserMethodFailure.Threw (_, exc)) ->
|
|
||||||
let stackTrace =
|
|
||||||
match stackTrace with
|
|
||||||
| None -> (exc : Exception).ToString ()
|
|
||||||
| Some s -> s
|
|
||||||
|
|
||||||
(Some stackTrace, message)
|
let timeout =
|
||||||
| TestFailure.TestFailed (UserMethodFailure.ReturnedNonUnit (_, ret))
|
match args.Timeout with
|
||||||
| TestFailure.SetUpFailed (UserMethodFailure.ReturnedNonUnit (_, ret))
|
| None -> TimeSpan.FromHours 2.0
|
||||||
| TestFailure.TearDownFailed (UserMethodFailure.ReturnedNonUnit (_, ret)) ->
|
| Some t -> t
|
||||||
let newMessage = $"returned non-unit value %O{ret}"
|
|
||||||
|
|
||||||
let message =
|
if not (results.Wait timeout) then
|
||||||
match message with
|
failwith "Tests failed to terminate within two hours"
|
||||||
| None -> newMessage
|
|
||||||
| Some message -> $"%s{message}\n%s{newMessage}"
|
|
||||||
|
|
||||||
(stackTrace, Some message)
|
let results = results.Result |> Seq.concat |> List.ofSeq
|
||||||
)
|
|
||||||
|> fun (stackTrace, message) ->
|
|
||||||
{
|
|
||||||
StackTrace = stackTrace
|
|
||||||
Message = message
|
|
||||||
}
|
|
||||||
|> Some
|
|
||||||
| Choice3Of3 (UserMethodFailure.Threw (_, exc)) ->
|
|
||||||
{
|
|
||||||
StackTrace = (exc : Exception).ToString () |> Some
|
|
||||||
Message = None
|
|
||||||
}
|
|
||||||
|> Some
|
|
||||||
| Choice3Of3 (UserMethodFailure.ReturnedNonUnit (_, ret)) ->
|
|
||||||
{
|
|
||||||
Message = $"returned non-unit value %O{ret}" |> Some
|
|
||||||
StackTrace = None
|
|
||||||
}
|
|
||||||
|> Some
|
|
||||||
|
|
||||||
let outcome =
|
let report = BuildTrxReport.build assy creationTime startTime results
|
||||||
match cause with
|
|
||||||
| Choice1Of3 _ -> TrxTestOutcome.Failed
|
|
||||||
| Choice2Of3 TestMemberSuccess.Ok -> TrxTestOutcome.Passed
|
|
||||||
| Choice2Of3 (TestMemberSuccess.Inconclusive _) -> TrxTestOutcome.Inconclusive
|
|
||||||
| Choice2Of3 (TestMemberSuccess.Ignored _)
|
|
||||||
| Choice2Of3 (TestMemberSuccess.Explicit _) -> TrxTestOutcome.NotExecuted
|
|
||||||
// TODO: we can totally do better here, more fine-grained classification
|
|
||||||
| Choice3Of3 _ -> TrxTestOutcome.Failed
|
|
||||||
|
|
||||||
{
|
match args.Trx with
|
||||||
ExecutionId = i.ExecutionId
|
|
||||||
TestId = i.TestId
|
|
||||||
TestName = i.TestName
|
|
||||||
ComputerName = i.ComputerName
|
|
||||||
Duration = i.End - i.Start
|
|
||||||
StartTime = i.Start
|
|
||||||
EndTime = i.End
|
|
||||||
TestType = magicGuid
|
|
||||||
Outcome = outcome
|
|
||||||
TestListId = testListId
|
|
||||||
RelativeResultsDirectory = i.ExecutionId.ToString () // for some reason
|
|
||||||
Output =
|
|
||||||
match i.StdOut, i.StdErr, exc with
|
|
||||||
| None, None, None -> None
|
|
||||||
| stdout, stderr, exc ->
|
|
||||||
Some
|
|
||||||
{
|
|
||||||
TrxOutput.StdOut = stdout
|
|
||||||
StdErr = stderr
|
|
||||||
ErrorInfo = exc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
let report : TrxReport =
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid ()
|
|
||||||
Name = $"@%s{hostname} %s{finishTimeHumanReadable}"
|
|
||||||
Times = times
|
|
||||||
Settings = settings
|
|
||||||
Results = results
|
|
||||||
TestDefinitions = testDefinitions
|
|
||||||
TestEntries = testEntries
|
|
||||||
TestLists = [ testList ]
|
|
||||||
ResultsSummary = resultSummary
|
|
||||||
}
|
|
||||||
|
|
||||||
match trxPath with
|
|
||||||
| Some trxPath ->
|
| Some trxPath ->
|
||||||
let contents = TrxReport.toXml report |> fun d -> d.OuterXml
|
let contents = TrxReport.toXml report |> fun d -> d.OuterXml
|
||||||
trxPath.Directory.Create ()
|
trxPath.Directory.Create ()
|
||||||
@@ -348,10 +86,56 @@ module Program =
|
|||||||
Console.Error.WriteLine $"Written TRX file: %s{trxPath.FullName}"
|
Console.Error.WriteLine $"Written TRX file: %s{trxPath.FullName}"
|
||||||
| None -> ()
|
| None -> ()
|
||||||
|
|
||||||
match outcome with
|
match report.ResultsSummary.Outcome with
|
||||||
| TrxOutcome.Completed -> 0
|
| TrxOutcome.Completed -> 0
|
||||||
| _ -> 1
|
| _ -> 1
|
||||||
|
|
||||||
|
let main argv =
|
||||||
|
let args = argv |> List.ofArray |> Args.Parse
|
||||||
|
|
||||||
|
let psi = ProcessStartInfo "dotnet"
|
||||||
|
|
||||||
|
match args.Trx with
|
||||||
|
| None -> ()
|
||||||
|
| Some trx -> psi.EnvironmentVariables.Add ("WOOFWARE_NUNIT_GENERATE_TRX", trx.FullName)
|
||||||
|
|
||||||
|
match args.LevelOfParallelism with
|
||||||
|
| None -> ()
|
||||||
|
| Some par -> psi.EnvironmentVariables.Add ("WOOFWARE_NUNIT_PARALLELISM_LEVEL", string<int> par)
|
||||||
|
|
||||||
|
match args.Filter with
|
||||||
|
| None -> ()
|
||||||
|
| Some (filter, _) -> psi.EnvironmentVariables.Add ("WOOFWARE_NUNIT_FILTER", filter)
|
||||||
|
|
||||||
|
match args.Timeout with
|
||||||
|
| None -> ()
|
||||||
|
| Some timeout ->
|
||||||
|
psi.EnvironmentVariables.Add ("WOOFWARE_NUNIT_TIMEOUT_SECS", string<int> (int<float> timeout.TotalSeconds))
|
||||||
|
|
||||||
|
psi.ArgumentList.Add "exec"
|
||||||
|
psi.ArgumentList.Add args.Dll.FullName
|
||||||
|
|
||||||
|
let us = Assembly.GetExecutingAssembly().Location |> FileInfo
|
||||||
|
|
||||||
|
let startupHook =
|
||||||
|
Path.Combine (us.Directory.FullName, "WoofWare.NUnitTestRunner.StartupHook.dll")
|
||||||
|
|
||||||
|
psi.EnvironmentVariables.Add ("DOTNET_STARTUP_HOOKS", startupHook)
|
||||||
|
|
||||||
|
psi.EnvironmentVariables.Add (
|
||||||
|
"WOOFWARE_NUNIT_LIB",
|
||||||
|
Path.Combine (us.Directory.FullName, "WoofWare.NUnitTestRunner.Lib.dll")
|
||||||
|
)
|
||||||
|
|
||||||
|
use proc = new Process ()
|
||||||
|
proc.StartInfo <- psi
|
||||||
|
|
||||||
|
if not (proc.Start ()) then
|
||||||
|
failwith "Failed to start dotnet"
|
||||||
|
|
||||||
|
proc.WaitForExit ()
|
||||||
|
proc.ExitCode
|
||||||
|
|
||||||
[<EntryPoint>]
|
[<EntryPoint>]
|
||||||
let reallyMain argv =
|
let reallyMain argv =
|
||||||
// Hack to make sure `finally`s get run.
|
// Hack to make sure `finally`s get run.
|
||||||
|
@@ -4,21 +4,21 @@ open Spectre.Console
|
|||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module Progress =
|
module Progress =
|
||||||
let spectre () : ITestProgress =
|
let spectre (console : IAnsiConsole) : ITestProgress =
|
||||||
{ new ITestProgress with
|
{ new ITestProgress with
|
||||||
member _.OnTestFailed name failure =
|
member _.OnTestFailed name failure =
|
||||||
AnsiConsole.Console.MarkupLine
|
console.MarkupLine
|
||||||
$"[red]Test '%s{Markup.Escape name}' failed: %s{Markup.Escape (failure.ToString ())}[/]"
|
$"[red]Test '%s{Markup.Escape name}' failed: %s{Markup.Escape (failure.ToString ())}[/]"
|
||||||
|
|
||||||
member _.OnTestFixtureStart name testCount =
|
member _.OnTestFixtureStart name testCount =
|
||||||
AnsiConsole.Console.MarkupLine $"[white]Running tests: %s{Markup.Escape name}[/]"
|
console.MarkupLine $"[white]Running tests: %s{Markup.Escape name}[/]"
|
||||||
|
|
||||||
member _.OnTestMemberFinished name =
|
member _.OnTestMemberFinished name =
|
||||||
AnsiConsole.Console.MarkupLine $"[gray]Finished test: %s{Markup.Escape name}[/]"
|
console.MarkupLine $"[gray]Finished test: %s{Markup.Escape name}[/]"
|
||||||
|
|
||||||
member _.OnTestMemberSkipped name =
|
member _.OnTestMemberSkipped name =
|
||||||
AnsiConsole.Console.MarkupLine $"[yellow]Skipping test due to filter: %s{Markup.Escape name}[/]"
|
console.MarkupLine $"[yellow]Skipping test due to filter: %s{Markup.Escape name}[/]"
|
||||||
|
|
||||||
member _.OnTestMemberStart name =
|
member _.OnTestMemberStart name =
|
||||||
AnsiConsole.Console.MarkupLine $"[white]Running test: %s{Markup.Escape name}[/]"
|
console.MarkupLine $"[white]Running test: %s{Markup.Escape name}[/]"
|
||||||
}
|
}
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
namespace WoofWare.NUnitTestRunner
|
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
|
||||||
module internal Seq =
|
|
||||||
|
|
||||||
let tryMinBy (f : 'a -> 'b) (s : 'a seq) : 'a option =
|
|
||||||
use enum = s.GetEnumerator ()
|
|
||||||
|
|
||||||
if not (enum.MoveNext ()) then
|
|
||||||
None
|
|
||||||
else
|
|
||||||
|
|
||||||
let mutable answer = enum.Current
|
|
||||||
let mutable fAnswer = f enum.Current
|
|
||||||
|
|
||||||
while enum.MoveNext () do
|
|
||||||
let fNext = f enum.Current
|
|
||||||
|
|
||||||
if fNext < fAnswer then
|
|
||||||
answer <- enum.Current
|
|
||||||
|
|
||||||
Some answer
|
|
@@ -16,12 +16,12 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ApiSurface" Version="4.0.41" />
|
<PackageReference Include="ApiSurface" Version="4.1.15" />
|
||||||
<PackageReference Include="FsCheck" Version="3.0.0-rc3" />
|
<PackageReference Include="FsCheck" Version="3.0.0-rc3" />
|
||||||
<PackageReference Include="FsUnit" Version="6.0.0" />
|
<PackageReference Include="FsUnit" Version="7.0.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
<PackageReference Include="NUnit" Version="4.3.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<RollForward>Major</RollForward>
|
||||||
<PackAsTool>true</PackAsTool>
|
<PackAsTool>true</PackAsTool>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<Authors>Patrick Stevens</Authors>
|
<Authors>Patrick Stevens</Authors>
|
||||||
@@ -19,7 +20,6 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Seq.fs" />
|
|
||||||
<Compile Include="Progress.fs" />
|
<Compile Include="Progress.fs" />
|
||||||
<Compile Include="Program.fs" />
|
<Compile Include="Program.fs" />
|
||||||
<None Include="..\README.md">
|
<None Include="..\README.md">
|
||||||
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\WoofWare.NUnitTestRunner.Lib\WoofWare.NUnitTestRunner.Lib.fsproj" />
|
<ProjectReference Include="..\WoofWare.NUnitTestRunner.Lib\WoofWare.NUnitTestRunner.Lib.fsproj" />
|
||||||
|
<ProjectReference Include="..\WoofWare.NUnitTestRunner.StartupHookLogic\WoofWare.NUnitTestRunner.StartupHookLogic.csproj" />
|
||||||
|
<ProjectReference Include="..\WoofWare.NUnitTestRunner.StartupHook\WoofWare.NUnitTestRunner.StartupHook.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
],
|
],
|
||||||
"pathFilters": [
|
"pathFilters": [
|
||||||
"./",
|
"./",
|
||||||
"^./WoofWare.NUnitTestRunner.Test",
|
":^WoofWare.NUnitTestRunner.Test",
|
||||||
":/WoofWare.NUnitTestRunner.Lib",
|
":/WoofWare.NUnitTestRunner.Lib",
|
||||||
":/Directory.Build.props",
|
":/Directory.Build.props",
|
||||||
":/README.md"
|
":/README.md"
|
||||||
|
@@ -4,13 +4,13 @@
|
|||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<IsPublishable>false</IsPublishable>
|
<IsPublishable>false</IsPublishable>
|
||||||
<RestorePackagesPath>../.analyzerpackages/</RestorePackagesPath>
|
<RestorePackagesPath>../.analyzerpackages/</RestorePackagesPath>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
|
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
|
||||||
<AutomaticallyUseReferenceAssemblyPackages>false</AutomaticallyUseReferenceAssemblyPackages> <!-- We don't want to build this project, so we do not need the reference assemblies for the framework we chose.-->
|
<AutomaticallyUseReferenceAssemblyPackages>false</AutomaticallyUseReferenceAssemblyPackages> <!-- We don't want to build this project, so we do not need the reference assemblies for the framework we chose.-->
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.10.0]" />
|
<PackageDownload Include="G-Research.FSharp.Analyzers" Version="[0.12.0]" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
12
flake.lock
generated
12
flake.lock
generated
@@ -5,11 +5,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710146030,
|
"lastModified": 1731533236,
|
||||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1717399147,
|
"lastModified": 1735915915,
|
||||||
"narHash": "sha256-eCWaE/q1VItpFAxxLVt171MdtDcjEnwi6QB/yuF73JU=",
|
"narHash": "sha256-Q4HuFAvoKAIiTRZTUxJ0ZXeTC7lLfC9/dggGHNXNlCw=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "4a4ecb0ab415c9fccfb005567a215e6a9564cdf5",
|
"rev": "a27871180d30ebee8aa6b11bf7fef8a52f024733",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
35
flake.nix
35
flake.nix
@@ -14,10 +14,10 @@
|
|||||||
flake-utils.lib.eachDefaultSystem (system: let
|
flake-utils.lib.eachDefaultSystem (system: let
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
pname = "unofficial-nunit-runner";
|
pname = "unofficial-nunit-runner";
|
||||||
dotnet-sdk = pkgs.dotnet-sdk_8;
|
dotnet-sdk = pkgs.dotnetCorePackages.sdk_8_0;
|
||||||
dotnet-runtime = pkgs.dotnetCorePackages.runtime_8_0;
|
dotnet-runtime = pkgs.dotnetCorePackages.runtime_8_0;
|
||||||
version = "0.1";
|
version = "0.1";
|
||||||
dotnetTool = dllOverride: toolName: toolVersion: sha256:
|
dotnetTool = dllOverride: toolName: toolVersion: hash:
|
||||||
pkgs.stdenvNoCC.mkDerivation rec {
|
pkgs.stdenvNoCC.mkDerivation rec {
|
||||||
name = toolName;
|
name = toolName;
|
||||||
version = toolVersion;
|
version = toolVersion;
|
||||||
@@ -25,8 +25,8 @@
|
|||||||
src = pkgs.fetchNuGet {
|
src = pkgs.fetchNuGet {
|
||||||
pname = name;
|
pname = name;
|
||||||
version = version;
|
version = version;
|
||||||
sha256 = sha256;
|
hash = hash;
|
||||||
installPhase = ''mkdir -p $out/bin && cp -r tools/net6.0/any/* $out/bin'';
|
installPhase = ''mkdir -p $out/bin && cp -r tools/net*/any/* $out/bin'';
|
||||||
};
|
};
|
||||||
installPhase = let
|
installPhase = let
|
||||||
dll =
|
dll =
|
||||||
@@ -42,9 +42,11 @@
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
packages = {
|
packages = let
|
||||||
fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).sha256;
|
deps = builtins.fromJSON (builtins.readFile ./nix/deps.json);
|
||||||
fsharp-analyzers = dotnetTool "FSharp.Analyzers.Cli" "fsharp-analyzers" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fsharp-analyzers.version (builtins.head (builtins.filter (elem: elem.pname == "fsharp-analyzers") ((import ./nix/deps.nix) {fetchNuGet = x: x;}))).sha256;
|
in {
|
||||||
|
fantomas = dotnetTool null "fantomas" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fantomas.version (builtins.head (builtins.filter (elem: elem.pname == "fantomas") deps)).hash;
|
||||||
|
fsharp-analyzers = dotnetTool "FSharp.Analyzers.Cli" "fsharp-analyzers" (builtins.fromJSON (builtins.readFile ./.config/dotnet-tools.json)).tools.fsharp-analyzers.version (builtins.head (builtins.filter (elem: elem.pname == "fsharp-analyzers") deps)).hash;
|
||||||
default = pkgs.buildDotnetModule {
|
default = pkgs.buildDotnetModule {
|
||||||
inherit pname version dotnet-sdk dotnet-runtime;
|
inherit pname version dotnet-sdk dotnet-runtime;
|
||||||
name = "unofficial-nunit-runner";
|
name = "unofficial-nunit-runner";
|
||||||
@@ -52,17 +54,20 @@
|
|||||||
projectFile = "./WoofWare.NUnitTestRunner/WoofWare.NUnitTestRunner.fsproj";
|
projectFile = "./WoofWare.NUnitTestRunner/WoofWare.NUnitTestRunner.fsproj";
|
||||||
testProjectFile = "./WoofWare.NUnitTestRunner/WoofWare.NUnitTestRunner.Test/WoofWare.NUnitTestRunner.Test.fsproj";
|
testProjectFile = "./WoofWare.NUnitTestRunner/WoofWare.NUnitTestRunner.Test/WoofWare.NUnitTestRunner.Test.fsproj";
|
||||||
disabledTests = ["WoofWare.NUnitTestRunner.Test.TestSurface.EnsureVersionIsMonotonic"];
|
disabledTests = ["WoofWare.NUnitTestRunner.Test.TestSurface.EnsureVersionIsMonotonic"];
|
||||||
nugetDeps = ./nix/deps.nix; # `nix build .#default.passthru.fetch-deps && ./result` and put the result here
|
nugetDeps = ./nix/deps.json; # `nix build .#default.fetch-deps && ./result nix/deps.json`
|
||||||
doCheck = true;
|
doCheck = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
devShell = pkgs.mkShell {
|
devShells = {
|
||||||
buildInputs = [dotnet-sdk];
|
default = pkgs.mkShell {
|
||||||
packages = [
|
packages = [
|
||||||
pkgs.alejandra
|
dotnet-sdk
|
||||||
pkgs.nodePackages.markdown-link-check
|
pkgs.alejandra
|
||||||
pkgs.shellcheck
|
pkgs.nodePackages.markdown-link-check
|
||||||
];
|
pkgs.shellcheck
|
||||||
|
pkgs.xmlstarlet
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
342
nix/deps.json
Normal file
342
nix/deps.json
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"pname": "ApiSurface",
|
||||||
|
"version": "4.1.15",
|
||||||
|
"hash": "sha256-E0J62c/viqvVBvBA5lBPG90BgPCrA6+cS/h4MZjKz+k="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "fantomas",
|
||||||
|
"version": "6.3.16",
|
||||||
|
"hash": "sha256-4tRdYf+/Q1iedx+DDuIKVGlIWQdr6erM51VdKzZkhCs="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Fantomas.Core",
|
||||||
|
"version": "6.1.1",
|
||||||
|
"hash": "sha256-FcTLHQFvKkQY/kV08jhhy/St/+FmXpp3epp/R3zUXMA="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Fantomas.FCS",
|
||||||
|
"version": "6.1.1",
|
||||||
|
"hash": "sha256-NuZ8msPEHYA8T3EYREB28F1RcNgUU8V54eg2+UttYxw="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "FsCheck",
|
||||||
|
"version": "3.0.0-rc3",
|
||||||
|
"hash": "sha256-4Z9Qv+vccrXWh2Fjdwdmjc1YgW+Dcx73ESkdAnHqxOY="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "fsharp-analyzers",
|
||||||
|
"version": "0.28.0",
|
||||||
|
"hash": "sha256-BqGk9MzHHA3oRPNfWuANcM1YELsdhzWI+kLF4mUDUx8="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "FSharp.Core",
|
||||||
|
"version": "6.0.1",
|
||||||
|
"hash": "sha256-Ehsgt3nCJijpaVuJguC1TPVEKSkJd6PSc07D2ZQSemI="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "FSharp.Core",
|
||||||
|
"version": "8.0.403",
|
||||||
|
"hash": "sha256-3XSQp7JUOU5T6gvSQXNfBF4t4gaX4J4xushH+cfM9mE="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "FsUnit",
|
||||||
|
"version": "7.0.1",
|
||||||
|
"hash": "sha256-K85CIdxMeFSHEKZk6heIXp/oFjWAn7dBILKrw49pJUY="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.AspNetCore.App.Ref",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-9jDkWbjw/nd8yqdzVTagCuqr6owJ/DUMi4BlUZT4hWU="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.AspNetCore.App.Runtime.linux-arm64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-JQULJyF0ivLoUU1JaFfK/HHg+/qzpN7V2RR2Cc+WlQ4="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.AspNetCore.App.Runtime.linux-x64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-zUsVIpV481vMLAXaLEEUpEMA9/f1HGOnvaQnaWdzlyY="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.AspNetCore.App.Runtime.osx-arm64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-2seqZcz0JeUjkzh3QcGa9TcJ4LUafpFjTRk+Nm8T6T0="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.AspNetCore.App.Runtime.osx-x64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-yxLafxiBKkvfkDggPk0P9YZIHBkDJOsFTO7/V9mEHuU="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.CodeCoverage",
|
||||||
|
"version": "17.12.0",
|
||||||
|
"hash": "sha256-lGjifppD0OBMBp28pjUfPipaeXg739n8cPhtHWoo5RE="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NET.Test.Sdk",
|
||||||
|
"version": "17.12.0",
|
||||||
|
"hash": "sha256-DKFEbhh2wPzahNeHdEoFig8tZh/LEVrFc5+zpT43Btg="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.App.Host.linux-arm64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-9lC/LYnthYhjkWWz2kkFCvlA5LJOv11jdt59SDnpdy0="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.App.Host.linux-x64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-VFRDzx7LJuvI5yzKdGmw/31NYVbwHWPKQvueQt5xc10="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.App.Host.osx-arm64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-DaSWwYACJGolEBuMhzDVCj/rQTdDt061xCVi+gyQnuo="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.App.Host.osx-x64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-FrRny9EI6HKCKQbu6mcLj5w4ooSRrODD4Vj2ZMGnMd4="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.App.Ref",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-9LZgVoIFF8qNyUu8kdJrYGLutMF/cL2K82HN2ywwlx8="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.App.Runtime.linux-arm64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-k3rxvUhCEU0pVH8KgEMtkPiSOibn+nBh+0zT2xIfId8="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.App.Runtime.linux-x64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-U8wJ2snSDFqeAgDVLXjnniidC7Cr5aJ1/h/BMSlyu0c="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.App.Runtime.osx-arm64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-UfLcrL2Gj/OLz0s92Oo+OCJeDpZFAcQLPLiSNND8D5Y="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.App.Runtime.osx-x64",
|
||||||
|
"version": "6.0.36",
|
||||||
|
"hash": "sha256-0xIJYFzxdMcnCj3wzkFRQZSnQcPHzPHMzePRIOA3oJs="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.Platforms",
|
||||||
|
"version": "1.1.1",
|
||||||
|
"hash": "sha256-8hLiUKvy/YirCWlFwzdejD2Db3DaXhHxT7GSZx/znJg="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.Platforms",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"hash": "sha256-IEvBk6wUXSdyCnkj6tHahOJv290tVVT8tyemYcR0Yro="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.NETCore.Targets",
|
||||||
|
"version": "1.1.3",
|
||||||
|
"hash": "sha256-WLsf1NuUfRWyr7C7Rl9jiua9jximnVvzy6nk2D2bVRc="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.TestPlatform.ObjectModel",
|
||||||
|
"version": "17.12.0",
|
||||||
|
"hash": "sha256-3XBHBSuCxggAIlHXmKNQNlPqMqwFlM952Av6RrLw1/w="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Microsoft.TestPlatform.TestHost",
|
||||||
|
"version": "17.12.0",
|
||||||
|
"hash": "sha256-rf8Sh0fQq44Sneuvs64unkkIHg8kOjDGWE35j9iLx5I="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Myriad.Core",
|
||||||
|
"version": "0.8.3",
|
||||||
|
"hash": "sha256-vBOxfq8QriX/yUtaXN69rEQaY/psRNJWxqATLidrt2g="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Myriad.Sdk",
|
||||||
|
"version": "0.8.3",
|
||||||
|
"hash": "sha256-7O397WKhskKOvE3MkJT37BvxorDWngDR6gTUogtDZ2M="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Nerdbank.GitVersioning",
|
||||||
|
"version": "3.7.112",
|
||||||
|
"hash": "sha256-vrItlaH5MpBHa4MI1cQgI11NAe4W3XsxR9DizFE7fus="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Newtonsoft.Json",
|
||||||
|
"version": "13.0.1",
|
||||||
|
"hash": "sha256-K2tSVW4n4beRPzPu3rlVaBEMdGvWSv/3Q1fxaDh4Mjo="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Newtonsoft.Json",
|
||||||
|
"version": "13.0.3",
|
||||||
|
"hash": "sha256-hy/BieY4qxBWVVsDqqOPaLy1QobiIapkbrESm6v2PHc="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "NuGet.Common",
|
||||||
|
"version": "6.12.1",
|
||||||
|
"hash": "sha256-k6JAFqHFinTakwNuW666aXYPhR7TpI/rb+KbHm1S2TM="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "NuGet.Configuration",
|
||||||
|
"version": "6.12.1",
|
||||||
|
"hash": "sha256-e/4lvyl7o7g4aWTAtr9S2yiGgk7V0E9p6DXpsy7GgVw="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "NuGet.Frameworks",
|
||||||
|
"version": "6.12.1",
|
||||||
|
"hash": "sha256-GGpkbas+PNLx35vvr3nyAVz5lY/aeoMx6qjmT368Lpg="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "NuGet.Packaging",
|
||||||
|
"version": "6.12.1",
|
||||||
|
"hash": "sha256-3h8Nmjpt383+dCg9GJ1BJ26UirwEQsWCPcTiT0+wGeI="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "NuGet.Protocol",
|
||||||
|
"version": "6.12.1",
|
||||||
|
"hash": "sha256-l+CHnAcit6Y9OjBxereRP5JzOuWbuZZQYkFOKsUkdQ8="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "NuGet.Versioning",
|
||||||
|
"version": "6.12.1",
|
||||||
|
"hash": "sha256-f/ejCuzCAwKs4N4Ec6yf2RovrhBT0nj0hRDP+03/Iy4="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "NUnit",
|
||||||
|
"version": "4.3.2",
|
||||||
|
"hash": "sha256-0RWe8uFoxYp6qhPlDDEghOMcKJgyw2ybvEoAqBLebeE="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "NUnit3TestAdapter",
|
||||||
|
"version": "4.6.0",
|
||||||
|
"hash": "sha256-9Yav2fYhC4w0OgsyUwU4/5rDy4FVDTpKnWHuwl/uKJQ="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "runtime.any.System.Runtime",
|
||||||
|
"version": "4.3.0",
|
||||||
|
"hash": "sha256-qwhNXBaJ1DtDkuRacgHwnZmOZ1u9q7N8j0cWOLYOELM="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "runtime.native.System",
|
||||||
|
"version": "4.3.0",
|
||||||
|
"hash": "sha256-ZBZaodnjvLXATWpXXakFgcy6P+gjhshFXmglrL5xD5Y="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "runtime.unix.System.Private.Uri",
|
||||||
|
"version": "4.3.0",
|
||||||
|
"hash": "sha256-c5tXWhE/fYbJVl9rXs0uHh3pTsg44YD1dJvyOA0WoMs="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "Spectre.Console",
|
||||||
|
"version": "0.49.1",
|
||||||
|
"hash": "sha256-tqSVojyuQjuB34lXo759NOcyLgNIw815mKXJPq5JFDo="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Diagnostics.DiagnosticSource",
|
||||||
|
"version": "7.0.0",
|
||||||
|
"hash": "sha256-9Wk8cHSkjKtqkN6xW7KnXoQVtF/VNbKeBq79WqDesMs="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Formats.Asn1",
|
||||||
|
"version": "8.0.1",
|
||||||
|
"hash": "sha256-may/Wg+esmm1N14kQTG4ESMBi+GQKPp0ZrrBo/o6OXM="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.IO.Abstractions",
|
||||||
|
"version": "4.2.13",
|
||||||
|
"hash": "sha256-nkC/PiqE6+c1HJ2yTwg3x+qdBh844Z8n3ERWDW8k6Gg="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.IO.FileSystem.AccessControl",
|
||||||
|
"version": "4.5.0",
|
||||||
|
"hash": "sha256-ck44YBQ0M+2Im5dw0VjBgFD1s0XuY54cujrodjjSBL8="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Memory",
|
||||||
|
"version": "4.5.5",
|
||||||
|
"hash": "sha256-EPQ9o1Kin7KzGI5O3U3PUQAZTItSbk9h/i4rViN3WiI="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Private.Uri",
|
||||||
|
"version": "4.3.0",
|
||||||
|
"hash": "sha256-fVfgcoP4AVN1E5wHZbKBIOPYZ/xBeSIdsNF+bdukIRM="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Reflection.Metadata",
|
||||||
|
"version": "1.6.0",
|
||||||
|
"hash": "sha256-JJfgaPav7UfEh4yRAQdGhLZF1brr0tUWPl6qmfNWq/E="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Runtime",
|
||||||
|
"version": "4.3.1",
|
||||||
|
"hash": "sha256-R9T68AzS1PJJ7v6ARz9vo88pKL1dWqLOANg4pkQjkA0="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Runtime.CompilerServices.Unsafe",
|
||||||
|
"version": "6.0.0",
|
||||||
|
"hash": "sha256-bEG1PnDp7uKYz/OgLOWs3RWwQSVYm+AnPwVmAmcgp2I="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Security.AccessControl",
|
||||||
|
"version": "4.5.0",
|
||||||
|
"hash": "sha256-AFsKPb/nTk2/mqH/PYpaoI8PLsiKKimaXf+7Mb5VfPM="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Security.Cryptography.Pkcs",
|
||||||
|
"version": "6.0.4",
|
||||||
|
"hash": "sha256-2e0aRybote+OR66bHaNiYpF//4fCiaO3zbR2e9GABUI="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Security.Cryptography.ProtectedData",
|
||||||
|
"version": "4.4.0",
|
||||||
|
"hash": "sha256-Ri53QmFX8I8UH0x4PikQ1ZA07ZSnBUXStd5rBfGWFOE="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Security.Principal.Windows",
|
||||||
|
"version": "4.5.0",
|
||||||
|
"hash": "sha256-BkUYNguz0e4NJp1kkW7aJBn3dyH9STwB5N8XqnlCsmY="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Text.Encodings.Web",
|
||||||
|
"version": "8.0.0",
|
||||||
|
"hash": "sha256-IUQkQkV9po1LC0QsqrilqwNzPvnc+4eVvq+hCvq8fvE="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Text.Json",
|
||||||
|
"version": "8.0.4",
|
||||||
|
"hash": "sha256-g5oT7fbXxQ9Iah1nMCr4UUX/a2l+EVjJyTrw3FTbIaI="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "TypeEquality",
|
||||||
|
"version": "0.3.0",
|
||||||
|
"hash": "sha256-V50xAOzzyUJrY+MYPRxtnqW5MVeATXCes89wPprv1r4="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "WoofWare.DotnetRuntimeLocator",
|
||||||
|
"version": "0.1.11",
|
||||||
|
"hash": "sha256-btWYnXxZzAnEcAE3Ufvz+Z3cJqtW7EGXs5OZMEHIWr8="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "WoofWare.Myriad.Plugins",
|
||||||
|
"version": "4.0.9",
|
||||||
|
"hash": "sha256-VWpStkuvdFZWsEs/tC0mjChneFgxWw+1YETH+3aCoz4="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "WoofWare.Myriad.Plugins.Attributes",
|
||||||
|
"version": "3.6.6",
|
||||||
|
"hash": "sha256-68T5JQNp4V0DDad0I3snVh8BCe7rz11mLyvm60hxwaA="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "WoofWare.PrattParser",
|
||||||
|
"version": "0.2.3",
|
||||||
|
"hash": "sha256-PsfU33BFsaA8LwlZMkSwmoA4hLb7Vkm2gYm48MglqxY="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pname": "WoofWare.Whippet.Fantomas",
|
||||||
|
"version": "0.3.1",
|
||||||
|
"hash": "sha256-i5oiqcrxzM90Ocuq5MIu2Ha5lV0aYu5nCvuwmFqp6NA="
|
||||||
|
}
|
||||||
|
]
|
269
nix/deps.nix
269
nix/deps.nix
@@ -1,269 +0,0 @@
|
|||||||
# This file was automatically generated by passthru.fetch-deps.
|
|
||||||
# Please dont edit it manually, your changes might get overwritten!
|
|
||||||
{fetchNuGet}: [
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "ApiSurface";
|
|
||||||
version = "4.0.41";
|
|
||||||
sha256 = "03kfa5ngmgkik9lc58sp8s9rrh9g40hhgjnrv662ks0d0y2i9i89";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "fantomas";
|
|
||||||
version = "6.3.9";
|
|
||||||
sha256 = "1b34iiiff02bbzjv03zyna8xmrgs6y87zdvp5i5k58fcqpjw44sx";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "FsCheck";
|
|
||||||
version = "3.0.0-rc3";
|
|
||||||
sha256 = "1rn4x9qh479927viwww3dy0mikcdcq3pfqv1hzbbawnwxfzm17z1";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "fsharp-analyzers";
|
|
||||||
version = "0.26.0";
|
|
||||||
sha256 = "0xgv5kvbwfdvcp6s8x7xagbbi4s3mqa4ixni6pazqvyflbgnah7b";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "FSharp.Core";
|
|
||||||
version = "6.0.0";
|
|
||||||
sha256 = "1hjhvr39c1vpgrdmf8xln5q86424fqkvy9nirkr29vl2461d2039";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "FSharp.Core";
|
|
||||||
version = "8.0.300";
|
|
||||||
sha256 = "158xxr9hnhz2ibyzzp2d249angvxfc58ifflm4g3hz8qx9zxaq04";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "FsUnit";
|
|
||||||
version = "6.0.0";
|
|
||||||
sha256 = "18q3p0z155znwj1l0qq3vq9nh9wl2i4mlfx4pmrnia4czr0xdkmb";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Ref";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "17k3l8xd5bsyk69bm5q4nxbpb4i0izw1kzmzi7j3p8pmm9prgrpy";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-arm64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "1n4v5przbrjhzj01b6qijpdc2jbsxr66ijvd0483qxh4s0b4jppr";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.linux-x64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "18v0l07q74m5xxaf6y6dkmr6and8ivya0nslffnr4djrxcbiygdr";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-arm64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "0p53lyqmr5n2ym202pbgmsd9b9aa6jar7ic04dcq86h2g77r5jqk";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.AspNetCore.App.Runtime.osx-x64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "009srl8vazkjnd93xr6k1m353spbki9gn1yzp4zgazgbrini6rqc";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.CodeCoverage";
|
|
||||||
version = "17.10.0";
|
|
||||||
sha256 = "0s0v7jmrq85n356xv7zixvwa4z94fszjcr5vll8x4im1a2lp00f9";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NET.Test.Sdk";
|
|
||||||
version = "17.10.0";
|
|
||||||
sha256 = "13g8fwl09li8fc71nk13dgkb7gahd4qhamyg2xby7am63nlchhdf";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Host.linux-arm64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "0l3gjhmnjd5n67w83smqyhmfcwzszafjgcbq8kdwxiwwh2m6nh2i";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Host.linux-x64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "0ss3108c2h7afypvliyqixv4dll60sq9iwqy90k1p132znpszrmb";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Host.osx-arm64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "08k5v35mvcs712kb0vcfjd1dsas5rgwrmv8rn87mzjb2p6ajl3n3";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Host.osx-x64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "02x38c68xan8hlr59mindcl4rcx49bbh4bibh6fw1l4rrijb38lw";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Ref";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "1wqqjhhlqz4dmijcx3kg3hnwq0s0jzqsddaksskzhq8avr4ziy18";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Runtime.linux-arm64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "0xfhcig3gj3986rxp3dhnd8hvnj4nvyhz1fz7kpx342d3g53wb37";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Runtime.linux-x64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "1s81sj8lnb8szqawxh3vc8wi815ln12cyhrl3f7hwcpay57xgswx";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Runtime.osx-arm64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "0s71k92daakzwish65gmn4nniy6bf2hv34c0sb6m1hv3criqxmp4";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.App.Runtime.osx-x64";
|
|
||||||
version = "6.0.30";
|
|
||||||
sha256 = "0xybqg2wd240r1nm2vrbn2qbfqfnqsmxn1012zzwjn17wa2si9a1";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.NETCore.Platforms";
|
|
||||||
version = "2.0.0";
|
|
||||||
sha256 = "1fk2fk2639i7nzy58m9dvpdnzql4vb8yl8vr19r2fp8lmj9w2jr0";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.TestPlatform.ObjectModel";
|
|
||||||
version = "17.10.0";
|
|
||||||
sha256 = "07j69cw8r39533w4p39mnj00kahazz38760in3jfc45kmlcdb26x";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Microsoft.TestPlatform.TestHost";
|
|
||||||
version = "17.10.0";
|
|
||||||
sha256 = "1bl471s7fx9jycr0cc8rylwf34mrvlg9qn1an6l86nisavfcyb7v";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Myriad.Sdk";
|
|
||||||
version = "0.8.3";
|
|
||||||
sha256 = "0qv78c5s5m04xb8h17nnn2ig26zcyya91k2dpj745cm1cbnzvvgc";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Nerdbank.GitVersioning";
|
|
||||||
version = "3.6.139";
|
|
||||||
sha256 = "0npcryhq3r0c2zi940jk39h13mzc4hyg7z8gm6jdmxi1aqv1vh8c";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Newtonsoft.Json";
|
|
||||||
version = "13.0.1";
|
|
||||||
sha256 = "0fijg0w6iwap8gvzyjnndds0q4b8anwxxvik7y8vgq97dram4srb";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Newtonsoft.Json";
|
|
||||||
version = "13.0.3";
|
|
||||||
sha256 = "0xrwysmrn4midrjal8g2hr1bbg38iyisl0svamb11arqws4w2bw7";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "NuGet.Common";
|
|
||||||
version = "6.10.0";
|
|
||||||
sha256 = "0nizrnilmlcqbm945293h8q3wfqfchb4xi8g50x4kjn0rbpd1kbh";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "NuGet.Configuration";
|
|
||||||
version = "6.10.0";
|
|
||||||
sha256 = "1aqaknaawnqx4mnvx9qw73wvj48jjzv0d78dzwl7m9zjlrl9myhz";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "NuGet.Frameworks";
|
|
||||||
version = "6.10.0";
|
|
||||||
sha256 = "0hrd8y31zx9a0wps49czw0qgbrakb49zn3abfgylc9xrq990zkqk";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "NuGet.Packaging";
|
|
||||||
version = "6.10.0";
|
|
||||||
sha256 = "18s53cvrf51lihmaqqdf48p2qi6ky1l48jv0hvbp76cxwdg7rba4";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "NuGet.Protocol";
|
|
||||||
version = "6.10.0";
|
|
||||||
sha256 = "0hmv4q0ks9i34mfgpb13l01la9v3jjllfh1qd3aqv105xrqrdxac";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "NuGet.Versioning";
|
|
||||||
version = "6.10.0";
|
|
||||||
sha256 = "1x19njx4x0sw9fz8y5fibi15xfsrw5avir0cx0599yd7p3ykik5g";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "NUnit";
|
|
||||||
version = "4.1.0";
|
|
||||||
sha256 = "0fj6xwgqaxq3mrai86bklclfmjkzf038mrslwfqf4ignaz9f7g5j";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "NUnit3TestAdapter";
|
|
||||||
version = "4.5.0";
|
|
||||||
sha256 = "1srx1629s0k1kmf02nmz251q07vj6pv58mdafcr5dr0bbn1fh78i";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "Spectre.Console";
|
|
||||||
version = "0.49.1";
|
|
||||||
sha256 = "0fhl96p3xjd5k1wwvhs80cp35rrlgnza6mw9vy0knhmf7ji9b95n";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "System.Formats.Asn1";
|
|
||||||
version = "6.0.0";
|
|
||||||
sha256 = "1vvr7hs4qzjqb37r0w1mxq7xql2b17la63jwvmgv65s1hj00g8r9";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "System.IO.Abstractions";
|
|
||||||
version = "4.2.13";
|
|
||||||
sha256 = "0s784iphsmj4vhkrzq9q3w39vsn76w44zclx3hsygsw458zbyh4y";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "System.IO.FileSystem.AccessControl";
|
|
||||||
version = "4.5.0";
|
|
||||||
sha256 = "1gq4s8w7ds1sp8f9wqzf8nrzal40q5cd2w4pkf4fscrl2ih3hkkj";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "System.Reflection.Metadata";
|
|
||||||
version = "1.6.0";
|
|
||||||
sha256 = "1wdbavrrkajy7qbdblpbpbalbdl48q3h34cchz24gvdgyrlf15r4";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "System.Security.AccessControl";
|
|
||||||
version = "4.5.0";
|
|
||||||
sha256 = "1wvwanz33fzzbnd2jalar0p0z3x0ba53vzx1kazlskp7pwyhlnq0";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "System.Security.Cryptography.Pkcs";
|
|
||||||
version = "6.0.4";
|
|
||||||
sha256 = "0hh5h38pnxmlrnvs72f2hzzpz4b2caiiv6xf8y7fzdg84r3imvfr";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "System.Security.Cryptography.ProtectedData";
|
|
||||||
version = "4.4.0";
|
|
||||||
sha256 = "1q8ljvqhasyynp94a1d7jknk946m20lkwy2c3wa8zw2pc517fbj6";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "System.Security.Principal.Windows";
|
|
||||||
version = "4.5.0";
|
|
||||||
sha256 = "0rmj89wsl5yzwh0kqjgx45vzf694v9p92r4x4q6yxldk1cv1hi86";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "System.Text.Encodings.Web";
|
|
||||||
version = "7.0.0";
|
|
||||||
sha256 = "1151hbyrcf8kyg1jz8k9awpbic98lwz9x129rg7zk1wrs6vjlpxl";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "System.Text.Json";
|
|
||||||
version = "7.0.3";
|
|
||||||
sha256 = "0zjrnc9lshagm6kdb9bdh45dmlnkpwcpyssa896sda93ngbmj8k9";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "WoofWare.DotnetRuntimeLocator";
|
|
||||||
version = "0.1.4";
|
|
||||||
sha256 = "19pp4qlyf18g704ppbcsm1rhjqjpi84py18yljj9nx70331m8bpg";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "WoofWare.Myriad.Plugins";
|
|
||||||
version = "2.1.44";
|
|
||||||
sha256 = "0rp9hpkah60gd9x0ba2izr9ff1g7yhzv5a4pkhi5fbrwf5rpqpwx";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "WoofWare.Myriad.Plugins.Attributes";
|
|
||||||
version = "3.1.6";
|
|
||||||
sha256 = "0786pr1p0nq0854mqi2cddmh185j3jihwn6azz9wiy6nxawjbrd2";
|
|
||||||
})
|
|
||||||
(fetchNuGet {
|
|
||||||
pname = "WoofWare.PrattParser";
|
|
||||||
version = "0.1.2";
|
|
||||||
sha256 = "0spypcwsbn805yrs6grjj68ccva902lhkq93mxy32rdply1xs34q";
|
|
||||||
})
|
|
||||||
]
|
|
Reference in New Issue
Block a user