diff --git a/.editorconfig b/.editorconfig
index d627e2a..205e89f 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -7,8 +7,11 @@ indent_style = space
[*.cs]
indent_size = 4
indent_style = space
+charset = utf-8
+insert_final_newline = true
+trim_trailing_whitespace = true
-# Require "this." keyword qualification in code
+# Prefer "this." qualification in product-style code
dotnet_style_qualification_for_field = true:suggestion
dotnet_style_qualification_for_property = true:suggestion
dotnet_style_qualification_for_method = true:suggestion
@@ -16,3 +19,17 @@ dotnet_style_qualification_for_event = true:suggestion
dotnet_diagnostic.CA1510.severity = suggestion
dotnet_diagnostic.CA1859.severity = suggestion
+
+# Prefer classic constructors on classes; primary constructors are fine on records.
+csharp_style_prefer_primary_constructors = false
+dotnet_diagnostic.IDE0290.severity = none
+
+# Tests: keep analyzers visible in the IDE, but do not fail Verify builds.
+# StyleCop is not referenced for test projects.
+[tests/**/*.cs]
+dotnet_analyzer_diagnostic.severity = suggestion
+dotnet_diagnostic.IDE0058.severity = none
+
+# Fixture/helpers intentionally break design rules (delegates, public fields, odd shapes).
+[tests/AutoFixture.TUnit.Tests/TestTypes/**.cs]
+dotnet_analyzer_diagnostic.severity = none
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index b29aad6..45e3f37 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -6,8 +6,8 @@
### Checklist
-- [ ] Reviewed the [contribution guidelines](https://github.com/AutoFixture/AutoFixture/blob/master/CONTRIBUTING.md)
+- [ ] Reviewed the [contribution guidelines](https://github.com/AutoFixture/AutoFixture.TUnit/blob/master/CONTRIBUTING.md)
- [ ] Linked the issue(s) the PR closes
- [ ] Implemented automated tests and checked coverage
- [ ] Provided inline documentation comments for new public API
-- [ ] Ran the full solution [build and validation](https://github.com/AutoFixture/AutoFixture#build) locally
+- [ ] Ran the full solution [build and validation](https://github.com/AutoFixture/AutoFixture.TUnit/blob/master/CONTRIBUTING.md#verification) locally
diff --git a/.github/workflows/continuous.yml b/.github/workflows/continuous.yml
index 95c7192..84d4066 100644
--- a/.github/workflows/continuous.yml
+++ b/.github/workflows/continuous.yml
@@ -27,16 +27,16 @@ jobs:
name: windows-latest
runs-on: windows-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v7
with:
fetch-depth: 0
- - uses: actions/setup-dotnet@v4
+ - uses: actions/setup-dotnet@v6
with:
dotnet-version: |
- 6.0.x
8.0.x
+ 10.0.x
- name: Cache .nuke/temp, ~/.nuget/packages
- uses: actions/cache@v4
+ uses: actions/cache@v6
with:
path: |
.nuke/temp
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d145954..afbaeb6 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -26,16 +26,16 @@ jobs:
name: windows-latest
runs-on: windows-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v7
with:
fetch-depth: 0
- - uses: actions/setup-dotnet@v4
+ - uses: actions/setup-dotnet@v6
with:
dotnet-version: |
- 6.0.x
8.0.x
+ 10.0.x
- name: Cache .nuke/temp, ~/.nuget/packages
- uses: actions/cache@v4
+ uses: actions/cache@v6
with:
path: |
.nuke/temp
@@ -46,15 +46,15 @@ jobs:
env:
GitHubToken: ${{ secrets.GITHUB_TOKEN }}
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@v7
with:
name: testresults
path: artifacts/testresults
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@v7
with:
name: reports
path: artifacts/reports
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@v7
with:
name: packages
path: artifacts/packages
diff --git a/AutoFixture.TUnit.Tests.globalconfig b/AutoFixture.TUnit.Tests.globalconfig
deleted file mode 100644
index 2b8356f..0000000
--- a/AutoFixture.TUnit.Tests.globalconfig
+++ /dev/null
@@ -1,654 +0,0 @@
-is_global = true
-global_level = 200
-
-# NOTE: No section headers for configuration entries
-
-#### .NET Coding Conventions ####
-
-## Naming conventions ##
-
-#### Diagnostic configuration ####
-
-## Managed code analysis ##
-
-dotnet_diagnostic.CA1000.severity = none
-dotnet_diagnostic.CA1001.severity = none
-dotnet_diagnostic.CA1002.severity = none
-dotnet_diagnostic.CA1003.severity = none
-dotnet_diagnostic.CA1004.severity = none
-dotnet_diagnostic.CA1005.severity = none
-dotnet_diagnostic.CA1006.severity = none
-dotnet_diagnostic.CA1007.severity = none
-dotnet_diagnostic.CA1008.severity = none
-dotnet_diagnostic.CA1009.severity = none
-dotnet_diagnostic.CA1010.severity = none
-dotnet_diagnostic.CA1011.severity = none
-dotnet_diagnostic.CA1012.severity = none
-dotnet_diagnostic.CA1013.severity = none
-dotnet_diagnostic.CA1014.severity = none
-dotnet_diagnostic.CA1016.severity = none
-dotnet_diagnostic.CA1017.severity = none
-dotnet_diagnostic.CA1018.severity = none
-dotnet_diagnostic.CA1019.severity = none
-dotnet_diagnostic.CA1020.severity = none
-dotnet_diagnostic.CA1021.severity = none
-dotnet_diagnostic.CA1023.severity = none
-dotnet_diagnostic.CA1024.severity = none
-dotnet_diagnostic.CA1025.severity = none
-dotnet_diagnostic.CA1026.severity = none
-dotnet_diagnostic.CA1027.severity = none
-dotnet_diagnostic.CA1028.severity = none
-dotnet_diagnostic.CA1030.severity = none
-dotnet_diagnostic.CA1031.severity = none
-dotnet_diagnostic.CA1032.severity = none
-dotnet_diagnostic.CA1033.severity = none
-dotnet_diagnostic.CA1034.severity = none
-dotnet_diagnostic.CA1035.severity = none
-dotnet_diagnostic.CA1036.severity = none
-dotnet_diagnostic.CA1038.severity = none
-dotnet_diagnostic.CA1039.severity = none
-dotnet_diagnostic.CA1040.severity = none
-dotnet_diagnostic.CA1041.severity = none
-dotnet_diagnostic.CA1043.severity = none
-dotnet_diagnostic.CA1044.severity = none
-dotnet_diagnostic.CA1045.severity = none
-dotnet_diagnostic.CA1046.severity = none
-dotnet_diagnostic.CA1047.severity = none
-dotnet_diagnostic.CA1048.severity = none
-dotnet_diagnostic.CA1049.severity = none
-dotnet_diagnostic.CA1050.severity = none
-dotnet_diagnostic.CA1051.severity = none
-dotnet_diagnostic.CA1052.severity = none
-dotnet_diagnostic.CA1053.severity = none
-dotnet_diagnostic.CA1054.severity = none
-dotnet_diagnostic.CA1055.severity = none
-dotnet_diagnostic.CA1056.severity = none
-dotnet_diagnostic.CA1057.severity = none
-dotnet_diagnostic.CA1058.severity = none
-dotnet_diagnostic.CA1059.severity = none
-dotnet_diagnostic.CA1060.severity = none
-dotnet_diagnostic.CA1061.severity = none
-dotnet_diagnostic.CA1062.severity = none
-dotnet_diagnostic.CA1063.severity = none
-dotnet_diagnostic.CA1064.severity = none
-dotnet_diagnostic.CA1065.severity = none
-dotnet_diagnostic.CA1300.severity = none
-dotnet_diagnostic.CA1301.severity = none
-dotnet_diagnostic.CA1302.severity = none
-dotnet_diagnostic.CA1303.severity = none
-dotnet_diagnostic.CA1304.severity = none
-dotnet_diagnostic.CA1305.severity = none
-dotnet_diagnostic.CA1306.severity = none
-dotnet_diagnostic.CA1307.severity = none
-dotnet_diagnostic.CA1308.severity = none
-dotnet_diagnostic.CA1309.severity = none
-dotnet_diagnostic.CA1400.severity = none
-dotnet_diagnostic.CA1401.severity = none
-dotnet_diagnostic.CA1402.severity = none
-dotnet_diagnostic.CA1403.severity = none
-dotnet_diagnostic.CA1404.severity = none
-dotnet_diagnostic.CA1405.severity = none
-dotnet_diagnostic.CA1406.severity = none
-dotnet_diagnostic.CA1407.severity = none
-dotnet_diagnostic.CA1408.severity = none
-dotnet_diagnostic.CA1409.severity = none
-dotnet_diagnostic.CA1410.severity = none
-dotnet_diagnostic.CA1411.severity = none
-dotnet_diagnostic.CA1412.severity = none
-dotnet_diagnostic.CA1413.severity = none
-dotnet_diagnostic.CA1414.severity = none
-dotnet_diagnostic.CA1415.severity = none
-dotnet_diagnostic.CA1500.severity = none
-dotnet_diagnostic.CA1501.severity = none
-dotnet_diagnostic.CA1502.severity = none
-dotnet_diagnostic.CA1504.severity = none
-dotnet_diagnostic.CA1505.severity = none
-dotnet_diagnostic.CA1506.severity = none
-dotnet_diagnostic.CA1600.severity = none
-dotnet_diagnostic.CA1601.severity = none
-dotnet_diagnostic.CA1700.severity = none
-dotnet_diagnostic.CA1701.severity = none
-dotnet_diagnostic.CA1702.severity = none
-dotnet_diagnostic.CA1703.severity = none
-dotnet_diagnostic.CA1704.severity = none
-dotnet_diagnostic.CA1707.severity = none
-dotnet_diagnostic.CA1708.severity = none
-dotnet_diagnostic.CA1709.severity = none
-dotnet_diagnostic.CA1710.severity = none
-dotnet_diagnostic.CA1711.severity = none
-dotnet_diagnostic.CA1712.severity = none
-dotnet_diagnostic.CA1713.severity = none
-dotnet_diagnostic.CA1714.severity = none
-dotnet_diagnostic.CA1715.severity = none
-dotnet_diagnostic.CA1716.severity = none
-dotnet_diagnostic.CA1717.severity = none
-dotnet_diagnostic.CA1719.severity = none
-dotnet_diagnostic.CA1720.severity = none
-dotnet_diagnostic.CA1721.severity = none
-dotnet_diagnostic.CA1722.severity = none
-dotnet_diagnostic.CA1724.severity = none
-dotnet_diagnostic.CA1725.severity = none
-dotnet_diagnostic.CA1726.severity = none
-dotnet_diagnostic.CA1800.severity = none
-dotnet_diagnostic.CA1801.severity = none
-dotnet_diagnostic.CA1802.severity = none
-dotnet_diagnostic.CA1804.severity = none
-dotnet_diagnostic.CA1806.severity = none
-dotnet_diagnostic.CA1809.severity = none
-dotnet_diagnostic.CA1810.severity = none
-dotnet_diagnostic.CA1811.severity = none
-dotnet_diagnostic.CA1812.severity = none
-dotnet_diagnostic.CA1813.severity = none
-dotnet_diagnostic.CA1814.severity = none
-dotnet_diagnostic.CA1815.severity = none
-dotnet_diagnostic.CA1816.severity = none
-dotnet_diagnostic.CA1819.severity = none
-dotnet_diagnostic.CA1820.severity = none
-dotnet_diagnostic.CA1821.severity = none
-dotnet_diagnostic.CA1822.severity = none
-dotnet_diagnostic.CA1823.severity = none
-dotnet_diagnostic.CA1824.severity = none
-dotnet_diagnostic.CA1825.severity = none
-dotnet_diagnostic.CA1900.severity = none
-dotnet_diagnostic.CA1901.severity = none
-dotnet_diagnostic.CA1903.severity = none
-dotnet_diagnostic.CA2000.severity = none
-dotnet_diagnostic.CA2001.severity = none
-dotnet_diagnostic.CA2002.severity = none
-dotnet_diagnostic.CA2003.severity = none
-dotnet_diagnostic.CA2004.severity = none
-dotnet_diagnostic.CA2006.severity = none
-dotnet_diagnostic.CA2100.severity = none
-dotnet_diagnostic.CA2101.severity = none
-dotnet_diagnostic.CA2102.severity = none
-dotnet_diagnostic.CA2103.severity = none
-dotnet_diagnostic.CA2104.severity = none
-dotnet_diagnostic.CA2105.severity = none
-dotnet_diagnostic.CA2106.severity = none
-dotnet_diagnostic.CA2107.severity = none
-dotnet_diagnostic.CA2108.severity = none
-dotnet_diagnostic.CA2109.severity = none
-dotnet_diagnostic.CA2111.severity = none
-dotnet_diagnostic.CA2112.severity = none
-dotnet_diagnostic.CA2114.severity = none
-dotnet_diagnostic.CA2115.severity = none
-dotnet_diagnostic.CA2116.severity = none
-dotnet_diagnostic.CA2117.severity = none
-dotnet_diagnostic.CA2118.severity = none
-dotnet_diagnostic.CA2119.severity = none
-dotnet_diagnostic.CA2120.severity = none
-dotnet_diagnostic.CA2121.severity = none
-dotnet_diagnostic.CA2122.severity = none
-dotnet_diagnostic.CA2123.severity = none
-dotnet_diagnostic.CA2124.severity = none
-dotnet_diagnostic.CA2126.severity = none
-dotnet_diagnostic.CA2130.severity = none
-dotnet_diagnostic.CA2131.severity = none
-dotnet_diagnostic.CA2132.severity = none
-dotnet_diagnostic.CA2133.severity = none
-dotnet_diagnostic.CA2134.severity = none
-dotnet_diagnostic.CA2135.severity = none
-dotnet_diagnostic.CA2136.severity = none
-dotnet_diagnostic.CA2137.severity = none
-dotnet_diagnostic.CA2138.severity = none
-dotnet_diagnostic.CA2139.severity = none
-dotnet_diagnostic.CA2140.severity = none
-dotnet_diagnostic.CA2141.severity = none
-dotnet_diagnostic.CA2142.severity = none
-dotnet_diagnostic.CA2143.severity = none
-dotnet_diagnostic.CA2144.severity = none
-dotnet_diagnostic.CA2145.severity = none
-dotnet_diagnostic.CA2146.severity = none
-dotnet_diagnostic.CA2147.severity = none
-dotnet_diagnostic.CA2149.severity = none
-dotnet_diagnostic.CA2151.severity = none
-dotnet_diagnostic.CA2200.severity = none
-dotnet_diagnostic.CA2201.severity = none
-dotnet_diagnostic.CA2202.severity = none
-dotnet_diagnostic.CA2204.severity = none
-dotnet_diagnostic.CA2205.severity = none
-dotnet_diagnostic.CA2207.severity = none
-dotnet_diagnostic.CA2208.severity = none
-dotnet_diagnostic.CA2210.severity = none
-dotnet_diagnostic.CA2211.severity = none
-dotnet_diagnostic.CA2212.severity = none
-dotnet_diagnostic.CA2213.severity = none
-dotnet_diagnostic.CA2214.severity = none
-dotnet_diagnostic.CA2215.severity = none
-dotnet_diagnostic.CA2216.severity = none
-dotnet_diagnostic.CA2217.severity = none
-dotnet_diagnostic.CA2218.severity = none
-dotnet_diagnostic.CA2219.severity = none
-dotnet_diagnostic.CA2220.severity = none
-dotnet_diagnostic.CA2221.severity = none
-dotnet_diagnostic.CA2222.severity = none
-dotnet_diagnostic.CA2223.severity = none
-dotnet_diagnostic.CA2224.severity = none
-dotnet_diagnostic.CA2225.severity = none
-dotnet_diagnostic.CA2226.severity = none
-dotnet_diagnostic.CA2227.severity = none
-dotnet_diagnostic.CA2228.severity = none
-dotnet_diagnostic.CA2229.severity = none
-dotnet_diagnostic.CA2230.severity = none
-dotnet_diagnostic.CA2231.severity = none
-dotnet_diagnostic.CA2232.severity = none
-dotnet_diagnostic.CA2233.severity = none
-dotnet_diagnostic.CA2234.severity = none
-dotnet_diagnostic.CA2235.severity = none
-dotnet_diagnostic.CA2236.severity = none
-dotnet_diagnostic.CA2237.severity = none
-dotnet_diagnostic.CA2238.severity = none
-dotnet_diagnostic.CA2239.severity = none
-dotnet_diagnostic.CA2240.severity = none
-dotnet_diagnostic.CA2241.severity = none
-dotnet_diagnostic.CA2242.severity = none
-dotnet_diagnostic.CA2243.severity = none
-dotnet_diagnostic.CA5122.severity = none
-
-## Security analysis ##
-
-dotnet_diagnostic.CA2300.severity = none
-
-## Native code analysis ##
-
-dotnet_diagnostic.C26100.severity = none
-dotnet_diagnostic.C26101.severity = none
-dotnet_diagnostic.C26105.severity = none
-dotnet_diagnostic.C26110.severity = none
-dotnet_diagnostic.C26111.severity = none
-dotnet_diagnostic.C26112.severity = none
-dotnet_diagnostic.C26115.severity = none
-dotnet_diagnostic.C26116.severity = none
-dotnet_diagnostic.C26117.severity = none
-dotnet_diagnostic.C26130.severity = none
-dotnet_diagnostic.C26135.severity = none
-dotnet_diagnostic.C26140.severity = none
-dotnet_diagnostic.C26160.severity = none
-dotnet_diagnostic.C26165.severity = none
-dotnet_diagnostic.C26166.severity = none
-dotnet_diagnostic.C26167.severity = none
-dotnet_diagnostic.C28020.severity = none
-dotnet_diagnostic.C28021.severity = none
-dotnet_diagnostic.C28022.severity = none
-dotnet_diagnostic.C28023.severity = none
-dotnet_diagnostic.C28024.severity = none
-dotnet_diagnostic.C28039.severity = none
-dotnet_diagnostic.C28101.severity = none
-dotnet_diagnostic.C28103.severity = none
-dotnet_diagnostic.C28104.severity = none
-dotnet_diagnostic.C28105.severity = none
-dotnet_diagnostic.C28106.severity = none
-dotnet_diagnostic.C28107.severity = none
-dotnet_diagnostic.C28108.severity = none
-dotnet_diagnostic.C28109.severity = none
-dotnet_diagnostic.C28110.severity = none
-dotnet_diagnostic.C28111.severity = none
-dotnet_diagnostic.C28112.severity = none
-dotnet_diagnostic.C28113.severity = none
-dotnet_diagnostic.C28114.severity = none
-dotnet_diagnostic.C28120.severity = none
-dotnet_diagnostic.C28121.severity = none
-dotnet_diagnostic.C28122.severity = none
-dotnet_diagnostic.C28123.severity = none
-dotnet_diagnostic.C28124.severity = none
-dotnet_diagnostic.C28125.severity = none
-dotnet_diagnostic.C28126.severity = none
-dotnet_diagnostic.C28127.severity = none
-dotnet_diagnostic.C28128.severity = none
-dotnet_diagnostic.C28129.severity = none
-dotnet_diagnostic.C28131.severity = none
-dotnet_diagnostic.C28132.severity = none
-dotnet_diagnostic.C28133.severity = none
-dotnet_diagnostic.C28134.severity = none
-dotnet_diagnostic.C28135.severity = none
-dotnet_diagnostic.C28137.severity = none
-dotnet_diagnostic.C28138.severity = none
-dotnet_diagnostic.C28141.severity = none
-dotnet_diagnostic.C28143.severity = none
-dotnet_diagnostic.C28144.severity = none
-dotnet_diagnostic.C28145.severity = none
-dotnet_diagnostic.C28146.severity = none
-dotnet_diagnostic.C28147.severity = none
-dotnet_diagnostic.C28150.severity = none
-dotnet_diagnostic.C28151.severity = none
-dotnet_diagnostic.C28152.severity = none
-dotnet_diagnostic.C28153.severity = none
-dotnet_diagnostic.C28156.severity = none
-dotnet_diagnostic.C28157.severity = none
-dotnet_diagnostic.C28158.severity = none
-dotnet_diagnostic.C28159.severity = none
-dotnet_diagnostic.C28160.severity = none
-dotnet_diagnostic.C28161.severity = none
-dotnet_diagnostic.C28162.severity = none
-dotnet_diagnostic.C28163.severity = none
-dotnet_diagnostic.C28164.severity = none
-dotnet_diagnostic.C28165.severity = none
-dotnet_diagnostic.C28166.severity = none
-dotnet_diagnostic.C28167.severity = none
-dotnet_diagnostic.C28168.severity = none
-dotnet_diagnostic.C28169.severity = none
-dotnet_diagnostic.C28170.severity = none
-dotnet_diagnostic.C28171.severity = none
-dotnet_diagnostic.C28172.severity = none
-dotnet_diagnostic.C28173.severity = none
-dotnet_diagnostic.C28175.severity = none
-dotnet_diagnostic.C28176.severity = none
-dotnet_diagnostic.C28182.severity = none
-dotnet_diagnostic.C28183.severity = none
-dotnet_diagnostic.C28193.severity = none
-dotnet_diagnostic.C28194.severity = none
-dotnet_diagnostic.C28195.severity = none
-dotnet_diagnostic.C28196.severity = none
-dotnet_diagnostic.C28197.severity = none
-dotnet_diagnostic.C28198.severity = none
-dotnet_diagnostic.C28199.severity = none
-dotnet_diagnostic.C28202.severity = none
-dotnet_diagnostic.C28203.severity = none
-dotnet_diagnostic.C28204.severity = none
-dotnet_diagnostic.C28205.severity = none
-dotnet_diagnostic.C28206.severity = none
-dotnet_diagnostic.C28207.severity = none
-dotnet_diagnostic.C28208.severity = none
-dotnet_diagnostic.C28209.severity = none
-dotnet_diagnostic.C28210.severity = none
-dotnet_diagnostic.C28211.severity = none
-dotnet_diagnostic.C28212.severity = none
-dotnet_diagnostic.C28213.severity = none
-dotnet_diagnostic.C28214.severity = none
-dotnet_diagnostic.C28215.severity = none
-dotnet_diagnostic.C28216.severity = none
-dotnet_diagnostic.C28217.severity = none
-dotnet_diagnostic.C28218.severity = none
-dotnet_diagnostic.C28219.severity = none
-dotnet_diagnostic.C28220.severity = none
-dotnet_diagnostic.C28221.severity = none
-dotnet_diagnostic.C28222.severity = none
-dotnet_diagnostic.C28223.severity = none
-dotnet_diagnostic.C28224.severity = none
-dotnet_diagnostic.C28225.severity = none
-dotnet_diagnostic.C28226.severity = none
-dotnet_diagnostic.C28227.severity = none
-dotnet_diagnostic.C28228.severity = none
-dotnet_diagnostic.C28229.severity = none
-dotnet_diagnostic.C28230.severity = none
-dotnet_diagnostic.C28231.severity = none
-dotnet_diagnostic.C28232.severity = none
-dotnet_diagnostic.C28233.severity = none
-dotnet_diagnostic.C28234.severity = none
-dotnet_diagnostic.C28235.severity = none
-dotnet_diagnostic.C28236.severity = none
-dotnet_diagnostic.C28237.severity = none
-dotnet_diagnostic.C28238.severity = none
-dotnet_diagnostic.C28239.severity = none
-dotnet_diagnostic.C28240.severity = none
-dotnet_diagnostic.C28241.severity = none
-dotnet_diagnostic.C28243.severity = none
-dotnet_diagnostic.C28244.severity = none
-dotnet_diagnostic.C28245.severity = none
-dotnet_diagnostic.C28246.severity = none
-dotnet_diagnostic.C28250.severity = none
-dotnet_diagnostic.C28251.severity = none
-dotnet_diagnostic.C28252.severity = none
-dotnet_diagnostic.C28253.severity = none
-dotnet_diagnostic.C28254.severity = none
-dotnet_diagnostic.C28260.severity = none
-dotnet_diagnostic.C28262.severity = none
-dotnet_diagnostic.C28263.severity = none
-dotnet_diagnostic.C28266.severity = none
-dotnet_diagnostic.C28267.severity = none
-dotnet_diagnostic.C28272.severity = none
-dotnet_diagnostic.C28273.severity = none
-dotnet_diagnostic.C28275.severity = none
-dotnet_diagnostic.C28278.severity = none
-dotnet_diagnostic.C28279.severity = none
-dotnet_diagnostic.C28280.severity = none
-dotnet_diagnostic.C28282.severity = none
-dotnet_diagnostic.C28283.severity = none
-dotnet_diagnostic.C28284.severity = none
-dotnet_diagnostic.C28285.severity = none
-dotnet_diagnostic.C28286.severity = none
-dotnet_diagnostic.C28287.severity = none
-dotnet_diagnostic.C28288.severity = none
-dotnet_diagnostic.C28289.severity = none
-dotnet_diagnostic.C28290.severity = none
-dotnet_diagnostic.C28291.severity = none
-dotnet_diagnostic.C28300.severity = none
-dotnet_diagnostic.C28301.severity = none
-dotnet_diagnostic.C28302.severity = none
-dotnet_diagnostic.C28303.severity = none
-dotnet_diagnostic.C28304.severity = none
-dotnet_diagnostic.C28305.severity = none
-dotnet_diagnostic.C28306.severity = none
-dotnet_diagnostic.C28307.severity = none
-dotnet_diagnostic.C28308.severity = none
-dotnet_diagnostic.C28309.severity = none
-dotnet_diagnostic.C28350.severity = none
-dotnet_diagnostic.C28351.severity = none
-dotnet_diagnostic.C28601.severity = none
-dotnet_diagnostic.C28602.severity = none
-dotnet_diagnostic.C28604.severity = none
-dotnet_diagnostic.C28615.severity = none
-dotnet_diagnostic.C28616.severity = none
-dotnet_diagnostic.C28617.severity = none
-dotnet_diagnostic.C28623.severity = none
-dotnet_diagnostic.C28624.severity = none
-dotnet_diagnostic.C28625.severity = none
-dotnet_diagnostic.C28636.severity = none
-dotnet_diagnostic.C28637.severity = none
-dotnet_diagnostic.C28638.severity = none
-dotnet_diagnostic.C28639.severity = none
-dotnet_diagnostic.C28640.severity = none
-dotnet_diagnostic.C28645.severity = none
-dotnet_diagnostic.C28648.severity = none
-dotnet_diagnostic.C28649.severity = none
-dotnet_diagnostic.C28650.severity = none
-dotnet_diagnostic.C28714.severity = none
-dotnet_diagnostic.C28715.severity = none
-dotnet_diagnostic.C28716.severity = none
-dotnet_diagnostic.C28717.severity = none
-dotnet_diagnostic.C28719.severity = none
-dotnet_diagnostic.C28720.severity = none
-dotnet_diagnostic.C28721.severity = none
-dotnet_diagnostic.C28726.severity = none
-dotnet_diagnostic.C28727.severity = none
-dotnet_diagnostic.C28730.severity = none
-dotnet_diagnostic.C28735.severity = none
-dotnet_diagnostic.C28736.severity = none
-dotnet_diagnostic.C28750.severity = none
-dotnet_diagnostic.C28751.severity = none
-dotnet_diagnostic.C6001.severity = none
-dotnet_diagnostic.C6011.severity = none
-dotnet_diagnostic.C6014.severity = none
-dotnet_diagnostic.C6029.severity = none
-dotnet_diagnostic.C6031.severity = none
-dotnet_diagnostic.C6053.severity = none
-dotnet_diagnostic.C6054.severity = none
-dotnet_diagnostic.C6059.severity = none
-dotnet_diagnostic.C6063.severity = none
-dotnet_diagnostic.C6064.severity = none
-dotnet_diagnostic.C6066.severity = none
-dotnet_diagnostic.C6067.severity = none
-dotnet_diagnostic.C6101.severity = none
-dotnet_diagnostic.C6200.severity = none
-dotnet_diagnostic.C6201.severity = none
-dotnet_diagnostic.C6211.severity = none
-dotnet_diagnostic.C6214.severity = none
-dotnet_diagnostic.C6215.severity = none
-dotnet_diagnostic.C6216.severity = none
-dotnet_diagnostic.C6217.severity = none
-dotnet_diagnostic.C6219.severity = none
-dotnet_diagnostic.C6220.severity = none
-dotnet_diagnostic.C6221.severity = none
-dotnet_diagnostic.C6225.severity = none
-dotnet_diagnostic.C6226.severity = none
-dotnet_diagnostic.C6230.severity = none
-dotnet_diagnostic.C6235.severity = none
-dotnet_diagnostic.C6236.severity = none
-dotnet_diagnostic.C6237.severity = none
-dotnet_diagnostic.C6239.severity = none
-dotnet_diagnostic.C6240.severity = none
-dotnet_diagnostic.C6242.severity = none
-dotnet_diagnostic.C6244.severity = none
-dotnet_diagnostic.C6246.severity = none
-dotnet_diagnostic.C6248.severity = none
-dotnet_diagnostic.C6250.severity = none
-dotnet_diagnostic.C6255.severity = none
-dotnet_diagnostic.C6258.severity = none
-dotnet_diagnostic.C6259.severity = none
-dotnet_diagnostic.C6260.severity = none
-dotnet_diagnostic.C6262.severity = none
-dotnet_diagnostic.C6263.severity = none
-dotnet_diagnostic.C6268.severity = none
-dotnet_diagnostic.C6269.severity = none
-dotnet_diagnostic.C6270.severity = none
-dotnet_diagnostic.C6271.severity = none
-dotnet_diagnostic.C6272.severity = none
-dotnet_diagnostic.C6273.severity = none
-dotnet_diagnostic.C6274.severity = none
-dotnet_diagnostic.C6276.severity = none
-dotnet_diagnostic.C6277.severity = none
-dotnet_diagnostic.C6278.severity = none
-dotnet_diagnostic.C6279.severity = none
-dotnet_diagnostic.C6280.severity = none
-dotnet_diagnostic.C6281.severity = none
-dotnet_diagnostic.C6282.severity = none
-dotnet_diagnostic.C6283.severity = none
-dotnet_diagnostic.C6284.severity = none
-dotnet_diagnostic.C6285.severity = none
-dotnet_diagnostic.C6286.severity = none
-dotnet_diagnostic.C6287.severity = none
-dotnet_diagnostic.C6288.severity = none
-dotnet_diagnostic.C6289.severity = none
-dotnet_diagnostic.C6290.severity = none
-dotnet_diagnostic.C6291.severity = none
-dotnet_diagnostic.C6292.severity = none
-dotnet_diagnostic.C6293.severity = none
-dotnet_diagnostic.C6294.severity = none
-dotnet_diagnostic.C6295.severity = none
-dotnet_diagnostic.C6296.severity = none
-dotnet_diagnostic.C6297.severity = none
-dotnet_diagnostic.C6298.severity = none
-dotnet_diagnostic.C6299.severity = none
-dotnet_diagnostic.C6302.severity = none
-dotnet_diagnostic.C6303.severity = none
-dotnet_diagnostic.C6305.severity = none
-dotnet_diagnostic.C6306.severity = none
-dotnet_diagnostic.C6308.severity = none
-dotnet_diagnostic.C6310.severity = none
-dotnet_diagnostic.C6312.severity = none
-dotnet_diagnostic.C6313.severity = none
-dotnet_diagnostic.C6314.severity = none
-dotnet_diagnostic.C6315.severity = none
-dotnet_diagnostic.C6316.severity = none
-dotnet_diagnostic.C6317.severity = none
-dotnet_diagnostic.C6318.severity = none
-dotnet_diagnostic.C6319.severity = none
-dotnet_diagnostic.C6320.severity = none
-dotnet_diagnostic.C6322.severity = none
-dotnet_diagnostic.C6323.severity = none
-dotnet_diagnostic.C6324.severity = none
-dotnet_diagnostic.C6326.severity = none
-dotnet_diagnostic.C6328.severity = none
-dotnet_diagnostic.C6329.severity = none
-dotnet_diagnostic.C6330.severity = none
-dotnet_diagnostic.C6331.severity = none
-dotnet_diagnostic.C6332.severity = none
-dotnet_diagnostic.C6333.severity = none
-dotnet_diagnostic.C6334.severity = none
-dotnet_diagnostic.C6335.severity = none
-dotnet_diagnostic.C6336.severity = none
-dotnet_diagnostic.C6340.severity = none
-dotnet_diagnostic.C6381.severity = none
-dotnet_diagnostic.C6383.severity = none
-dotnet_diagnostic.C6384.severity = none
-dotnet_diagnostic.C6385.severity = none
-dotnet_diagnostic.C6386.severity = none
-dotnet_diagnostic.C6387.severity = none
-dotnet_diagnostic.C6388.severity = none
-dotnet_diagnostic.C6400.severity = none
-dotnet_diagnostic.C6401.severity = none
-dotnet_diagnostic.C6411.severity = none
-dotnet_diagnostic.C6412.severity = none
-dotnet_diagnostic.C6500.severity = none
-dotnet_diagnostic.C6501.severity = none
-dotnet_diagnostic.C6503.severity = none
-dotnet_diagnostic.C6504.severity = none
-dotnet_diagnostic.C6505.severity = none
-dotnet_diagnostic.C6506.severity = none
-dotnet_diagnostic.C6508.severity = none
-dotnet_diagnostic.C6509.severity = none
-dotnet_diagnostic.C6510.severity = none
-dotnet_diagnostic.C6511.severity = none
-dotnet_diagnostic.C6513.severity = none
-dotnet_diagnostic.C6514.severity = none
-dotnet_diagnostic.C6515.severity = none
-dotnet_diagnostic.C6516.severity = none
-dotnet_diagnostic.C6517.severity = none
-dotnet_diagnostic.C6518.severity = none
-dotnet_diagnostic.C6522.severity = none
-dotnet_diagnostic.C6525.severity = none
-dotnet_diagnostic.C6527.severity = none
-dotnet_diagnostic.C6530.severity = none
-dotnet_diagnostic.C6540.severity = none
-dotnet_diagnostic.C6551.severity = none
-dotnet_diagnostic.C6552.severity = none
-dotnet_diagnostic.C6701.severity = none
-dotnet_diagnostic.C6702.severity = none
-dotnet_diagnostic.C6703.severity = none
-dotnet_diagnostic.C6704.severity = none
-dotnet_diagnostic.C6705.severity = none
-dotnet_diagnostic.C6706.severity = none
-dotnet_diagnostic.C6707.severity = none
-dotnet_diagnostic.C6993.severity = none
-dotnet_diagnostic.C6995.severity = none
-dotnet_diagnostic.C6997.severity = none
-
-
-## Runtime analysis ##
-
-dotnet_diagnostic.CA1825.severity = none # CA1825: Avoid zero-length array allocations
-
-## Tasks analysis ##
-
-dotnet_diagnostic.RS0018.severity = none
-
-## Documentation ##
-
-dotnet_diagnostic.RS0010.severity = none
-
-## StyleCop Analyzers ##
-
-dotnet_diagnostic.SA0001.severity = none # SA0001: XML comment analysis is disabled due to project configuration
-dotnet_diagnostic.SA1116.severity = none # SA1116: The parameters should begin on the line after the declaration, whenever the parameter span across multiple line
-dotnet_diagnostic.SA1117.severity = none # SA1117: The parameters should all be placed on the same line or each parameter should be placed on its own line.
-dotnet_diagnostic.SA1118.severity = none # SA1118: The parameter spans multiple lines
-dotnet_diagnostic.SA1133.severity = none # SA1133: Each attribute should be placed in its own set of square brackets.
-dotnet_diagnostic.SA1200.severity = none # SA1200: Using directive should appear within a namespace declaration
-dotnet_diagnostic.SA1201.severity = none # SA1201: A property should not follow a method
-dotnet_diagnostic.SA1202.severity = none # SA1202: 'public' members should come before 'private' members
-dotnet_diagnostic.SA1203.severity = none # SA1203: Constant fields should appear before non-constant fields
-dotnet_diagnostic.SA1204.severity = none # SA1204: Static members should appear before non-static members
-dotnet_diagnostic.SA1214.severity = none # SA1214: Readonly fields should appear before non-readonly fields
-dotnet_diagnostic.SA1401.severity = none # SA1401: Field should be private
-dotnet_diagnostic.SA1402.severity = none # SA1402: File may only contain a single type
-dotnet_diagnostic.SA1413.severity = none # SA1413: Use trailing comma in multi-line initializers
-dotnet_diagnostic.SA1501.severity = none # SA1501: Statement should not be on a single line
-dotnet_diagnostic.SA1503.severity = none # SA1503: Braces should not be omitted
-dotnet_diagnostic.SA1513.severity = none # SA1513: Closing brace should be followed by blank line
-dotnet_diagnostic.SA1515.severity = none # SA1515: Single-line comment should be preceded by blank line
-dotnet_diagnostic.SA1516.severity = none # SA1516: Elements should be separated by blank line
-dotnet_diagnostic.SA1600.severity = none # SA1600: Elements should be documented
-dotnet_diagnostic.SA1604.severity = none # SA1604: Element documentation should have summary
-dotnet_diagnostic.SA1610.severity = none # SA1610: Property documentation should have value text
-dotnet_diagnostic.SA1611.severity = none # SA1611: The documentation for parameter 'predicate' is missing
-dotnet_diagnostic.SA1612.severity = none # SA1612: The parameter documentation for 'context' should be at position 1.
-dotnet_diagnostic.SA1614.severity = none # SA1614: Element parameter documentation should have text
-dotnet_diagnostic.SA1615.severity = none # SA1615: Element return value should be documented
-dotnet_diagnostic.SA1616.severity = none # SA1616: Element return value documentation should have text
-dotnet_diagnostic.SA1618.severity = none # SA1618: The documentation for type parameter 'TProperty' is missing
-dotnet_diagnostic.SA1622.severity = none # SA1622: Generic type parameter documentation should have text.
-dotnet_diagnostic.SA1623.severity = none # SA1623: The property's documentation summary text should begin with: 'Gets'
-dotnet_diagnostic.SA1625.severity = none # SA1625: Element documentation should not be copied and pasted
-dotnet_diagnostic.SA1627.severity = none # SA1627: The documentation text within the \'exception\' tag should not be empty.
-dotnet_diagnostic.SA1633.severity = none # SA1633: The file header is missing or not located at the top of the file.
-dotnet_diagnostic.SA1642.severity = none # SA1642: Constructor summary documentation should begin with standard text
diff --git a/AutoFixture.TUnit.globalconfig b/AutoFixture.TUnit.globalconfig
index 3f911a7..66900ba 100644
--- a/AutoFixture.TUnit.globalconfig
+++ b/AutoFixture.TUnit.globalconfig
@@ -1,58 +1,52 @@
is_global = true
global_level = 100
-# NOTE: No section headers for configuration entries
-
-#### .NET Coding Conventions ####
-
-## Naming conventions ##
-
#### Diagnostic configuration ####
## Managed code analysis ##
-dotnet_diagnostic.CA1006.severity = none # CA1006: Do not nest generic types in member signatures
-dotnet_diagnostic.CA1020.severity = none # CA1020: Avoid namespaces with few types
-dotnet_diagnostic.CA1303.severity = none # CA1303: Do not pass literals as localized parameters
-dotnet_diagnostic.CA2243.severity = none # CA2243: Attribute string literals should parse correctly
+dotnet_diagnostic.CA1006.severity = none # Do not nest generic types in member signatures
+dotnet_diagnostic.CA1020.severity = none # Avoid namespaces with few types
+dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters
+dotnet_diagnostic.CA2243.severity = none # Attribute string literals should parse correctly
## Runtime analysis ##
-dotnet_diagnostic.CA1825.severity = none # CA1825: Avoid zero-length array allocations
+dotnet_diagnostic.CA1825.severity = none # Avoid zero-length array allocations
## Security ##
-dotnet_diagnostic.CA5394.severity = none # CA5394: Do not use insecure randomness
+dotnet_diagnostic.CA5394.severity = none # Do not use insecure randomness
## StyleCop Analyzers ##
-dotnet_diagnostic.SA1101.severity = none # SA1101: Prefix local calls with this.
-dotnet_diagnostic.SA1116.severity = none # SA1116: The parameters should begin on the line after the declaration, whenever the parameter span across multiple line
-dotnet_diagnostic.SA1117.severity = none # SA1117: The parameters should all be placed on the same line or each parameter should be placed on its own line.
-dotnet_diagnostic.SA1118.severity = none # SA1118: The parameter spans multiple lines
-dotnet_diagnostic.SA1200.severity = none # SA1200: Using directive should appear within a namespace declaration
-dotnet_diagnostic.SA1201.severity = none # SA1201: A property should not follow a method
-dotnet_diagnostic.SA1202.severity = none # SA1202: 'public' members should come before 'private' members
-dotnet_diagnostic.SA1203.severity = none # SA1203: Constant fields should appear before non-constant fields
-dotnet_diagnostic.SA1204.severity = none # SA1204: Static members should appear before non-static members
-dotnet_diagnostic.SA1214.severity = none # SA1214: Readonly fields should appear before non-readonly fields
-dotnet_diagnostic.SA1309.severity = none # SA1309: Field names should not begin with an underscore
-dotnet_diagnostic.SA1413.severity = none # SA1413: Use trailing comma in multi-line initializers
-dotnet_diagnostic.SA1501.severity = none # SA1501: Statement should not be on a single line
-dotnet_diagnostic.SA1503.severity = none # SA1503: Braces should not be omitted
-dotnet_diagnostic.SA1513.severity = none # SA1513: Closing brace should be followed by blank line
-dotnet_diagnostic.SA1600.severity = none # SA1600: Elements should be documented
-dotnet_diagnostic.SA1604.severity = none # SA1604: Element documentation should have summary
-dotnet_diagnostic.SA1610.severity = none # SA1610: Property documentation should have value text
-dotnet_diagnostic.SA1611.severity = none # SA1611: The documentation for parameter 'predicate' is missing
-dotnet_diagnostic.SA1612.severity = none # SA1612: The parameter documentation for 'context' should be at position 1.
-dotnet_diagnostic.SA1614.severity = none # SA1614: Element parameter documentation should have text
-dotnet_diagnostic.SA1615.severity = none # SA1615: Element return value should be documented
-dotnet_diagnostic.SA1616.severity = none # SA1616: Element return value documentation should have text
-dotnet_diagnostic.SA1618.severity = none # SA1618: The documentation for type parameter 'TProperty' is missing
-dotnet_diagnostic.SA1622.severity = none # SA1622: Generic type parameter documentation should have text.
-dotnet_diagnostic.SA1623.severity = none # SA1623: The property's documentation summary text should begin with: 'Gets'
-dotnet_diagnostic.SA1625.severity = none # SA1625: Element documentation should not be copied and pasted
-dotnet_diagnostic.SA1627.severity = none # SA1627: The documentation text within the \'exception\' tag should not be empty.
-dotnet_diagnostic.SA1633.severity = none # SA1633: The file header is missing or not located at the top of the file.
-dotnet_diagnostic.SA1642.severity = none # SA1642: Constructor summary documentation should begin with standard text
\ No newline at end of file
+dotnet_diagnostic.SA1101.severity = none # Prefix local calls with this.
+dotnet_diagnostic.SA1116.severity = none # Parameters should begin on the line after the declaration
+dotnet_diagnostic.SA1117.severity = none # Parameters should all be on the same line or each on its own line
+dotnet_diagnostic.SA1118.severity = none # Parameter spans multiple lines
+dotnet_diagnostic.SA1200.severity = none # Using directive should appear within a namespace declaration
+dotnet_diagnostic.SA1201.severity = none # A property should not follow a method
+dotnet_diagnostic.SA1202.severity = none # 'public' members should come before 'private' members
+dotnet_diagnostic.SA1203.severity = none # Constant fields should appear before non-constant fields
+dotnet_diagnostic.SA1204.severity = none # Static members should appear before non-static members
+dotnet_diagnostic.SA1214.severity = none # Readonly fields should appear before non-readonly fields
+dotnet_diagnostic.SA1309.severity = none # Field names should not begin with an underscore
+dotnet_diagnostic.SA1413.severity = none # Use trailing comma in multi-line initializers
+dotnet_diagnostic.SA1501.severity = none # Statement should not be on a single line
+dotnet_diagnostic.SA1503.severity = none # Braces should not be omitted
+dotnet_diagnostic.SA1513.severity = none # Closing brace should be followed by blank line
+dotnet_diagnostic.SA1600.severity = none # Elements should be documented
+dotnet_diagnostic.SA1604.severity = none # Element documentation should have summary
+dotnet_diagnostic.SA1610.severity = none # Property documentation should have value text
+dotnet_diagnostic.SA1611.severity = none # Parameter documentation is missing
+dotnet_diagnostic.SA1612.severity = none # Parameter documentation order
+dotnet_diagnostic.SA1614.severity = none # Element parameter documentation should have text
+dotnet_diagnostic.SA1615.severity = none # Element return value should be documented
+dotnet_diagnostic.SA1616.severity = none # Element return value documentation should have text
+dotnet_diagnostic.SA1618.severity = none # Type parameter documentation is missing
+dotnet_diagnostic.SA1622.severity = none # Generic type parameter documentation should have text
+dotnet_diagnostic.SA1623.severity = none # Property documentation summary text should begin with 'Gets'
+dotnet_diagnostic.SA1625.severity = none # Element documentation should not be copied and pasted
+dotnet_diagnostic.SA1627.severity = none # Documentation text within the 'exception' tag should not be empty
+dotnet_diagnostic.SA1633.severity = none # The file header is missing or not located at the top of the file
+dotnet_diagnostic.SA1642.severity = none # Constructor summary documentation should begin with standard text
diff --git a/AutoFixture.TUnit.sln.DotSettings b/AutoFixture.TUnit.sln.DotSettings
index dac263b..fcf6df8 100644
--- a/AutoFixture.TUnit.sln.DotSettings
+++ b/AutoFixture.TUnit.sln.DotSettings
@@ -12,7 +12,6 @@
True
True
True
- <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
<Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy>
True
True
@@ -26,18 +25,19 @@
True
True
True
- xUnit fact template
+ TUnit test template
True
0
True
True
Everywhere
- fact
+ test
True
- [Fact]
+ [Test]
public void $NAME$()
{
// Arrange$END$
// Act
// Assert
-}
+}
+
diff --git a/AutoFixtureLogo200x200.png b/AutoFixtureLogo200x200.png
deleted file mode 100644
index 32a82c5..0000000
Binary files a/AutoFixtureLogo200x200.png and /dev/null differ
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..85c6668
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,66 @@
+# How to contribute to AutoFixture.TUnit
+
+AutoFixture.TUnit is developed in modern C# on .NET using [TUnit](https://github.com/thomhurst/TUnit) as the unit testing framework.
+The library targets `netstandard2.0`, `net8.0`, and `net10.0`. Development uses the .NET SDK version pinned in `global.json` (currently .NET 10 with latest-minor roll-forward).
+
+So far, development has been done with a strong focus on automated tests, and the aim is to keep it that way.
+
+## Code of Conduct
+
+This project follows the [AutoFixture Code of Conduct](https://github.com/AutoFixture/AutoFixture/blob/master/CODE_OF_CONDUCT.md). It applies to all interactions within the project.
+
+## Issues
+
+Use [Issues](https://github.com/AutoFixture/AutoFixture.TUnit/issues) for confirmed bugs, tasks, and vulnerability reports.
+For questions and feature ideas, prefer starting a discussion with maintainers before a large pull request.
+
+When opening a new issue, follow the instructions in the issue template. Do not alter the template structure.
+
+## Build
+
+AutoFixture.TUnit uses [NUKE](https://nuke.build/) as a build engine. From the repository root, run:
+
+```sh
+./build.cmd
+```
+
+On Windows PowerShell you can also run `.\build.ps1`.
+
+The repository state (last tag and commits since that tag) determines the build version via [GitVersion](https://gitversion.net/).
+
+Use `./build.cmd --help` for supported parameters and targets.
+
+## Verification
+
+The Verify configuration treats analyzer warnings as errors for the product library.
+Test projects do not use StyleCop; prefer `.editorconfig` and light analyzers there.
+
+Before opening a PR, run the following from the repository root.
+This verifies coding rules, runs the full test suite, and writes an HTML coverage report under `./artifacts/reports/`:
+
+```sh
+./build.cmd Verify Cover --no-logo --configuration Release
+```
+
+## Pull requests
+
+When contributing, follow the coding style already present in the repository.
+Keep line lengths under 120 characters when practical so reviews stay readable on GitHub.
+
+Please follow common [Open Source Contribution Etiquette](http://tirania.org/blog/archive/2010/Dec-31.html): fork the repo, keep pull requests focused on one change, and be ready to iterate on review feedback.
+
+For larger ideas, open an issue first so maintainers can confirm direction.
+
+## Versioning
+
+AutoFixture.TUnit follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html) for public releases on [nuget.org](https://www.nuget.org/).
+
+## Continuous Integration
+
+CI runs on [GitHub Actions](https://github.com/AutoFixture/AutoFixture.TUnit/actions) for pull requests and releases.
+The Nuke build typically:
+
+1. Compiles the solution
+2. Runs static analysis (Verify)
+3. Runs tests with coverage (Cover)
+4. Packs NuGet packages (and publishes on tagged releases)
diff --git a/Common.Test.props b/Common.Test.props
index f0100ac..2cc1ee9 100644
--- a/Common.Test.props
+++ b/Common.Test.props
@@ -16,21 +16,19 @@
false
+
+
+
+ $(NoWarn);CS8632;CA1707;IDE0058
+
true
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
-
-
+
+
diff --git a/Common.props b/Common.props
index 5cebd21..55c0839 100644
--- a/Common.props
+++ b/Common.props
@@ -31,7 +31,6 @@
https://github.com/AutoFixture/AutoFixture.TUnit
true
MIT
- https://raw.githubusercontent.com/AutoFixture/AutoFixture.TUnit/master/AutoFixtureLogo200x200.png
icon.png
README.md
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
@@ -43,8 +42,9 @@
-
-
+
+
+
diff --git a/README.md b/README.md
index 648ea90..067685e 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,18 @@
[](https://raw.githubusercontent.com/AutoFixture/AutoFixture.TUnit/master/LICENCE.txt)
[](https://www.nuget.org/packages/AutoFixture.TUnit)
-[AutoFixture.TUnit](https://github.com/AutoFixture/AutoFixture.TUnit) is a .NET library that integrates [AutoFixture](https://github.com/AutoFixture/AutoFixture) with [TUnit](https://github.com/tunitframework/tunit), allowing you to effortlessly generate test data for your unit tests.
+[AutoFixture.TUnit](https://github.com/AutoFixture/AutoFixture.TUnit) is a .NET library that integrates [AutoFixture](https://github.com/AutoFixture/AutoFixture) with [TUnit](https://github.com/thomhurst/TUnit), allowing you to effortlessly generate test data for your unit tests.
By leveraging the data generators feature of TUnit, this extension turns AutoFixture into a declarative framework for writing unit tests. In many ways it becomes a unit testing DSL (Domain Specific Language).
+
+
+
+
+
+
+
+
+
## Table of Contents
- [Installation](#installation)
@@ -16,8 +25,8 @@ By leveraging the data generators feature of TUnit, this extension turns AutoFix
## Installation
-AutoFixture packages are distributed via NuGet.
-To install the packages you can use the integrated package manager of your IDE, the .NET CLI, or reference the package directly in your project file.
+AutoFixture.TUnit is distributed via NuGet.
+To install the package you can use the integrated package manager of your IDE, the .NET CLI, or reference the package directly in your project file.
```cmd
dotnet add package AutoFixture.TUnit
@@ -41,6 +50,7 @@ public class Calculator
You can write a test using AutoFixture to provide the input values:
```csharp
+using TUnit;
using TUnit.Assertions;
using AutoFixture.TUnit;
@@ -65,6 +75,7 @@ You can also combine auto-generated data with inline arguments using the `[AutoA
This allows you to specify some parameters while still letting AutoFixture generate the rest.
```csharp
+using TUnit;
using TUnit.Assertions;
using AutoFixture.TUnit;
@@ -84,6 +95,141 @@ public class CalculatorTests
}
```
+### Member and Class Data Sources
+
+Use `[AutoMemberDataSource]` when some values come from a static member (property, field, or method).
+Use `[AutoClassDataSource]` when values come from a separate data provider type.
+Any remaining test parameters are filled by AutoFixture.
+
+Supported member/class result shapes (same ideas as TUnit MethodDataSource):
+
+| Result shape | How it becomes test rows |
+| --- | --- |
+| `IEnumerable
diff --git a/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute.cs b/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute.cs
index 8202518..7d6b3a8 100644
--- a/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute.cs
+++ b/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute.cs
@@ -1,4 +1,4 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
using AutoFixture.TUnit.Internal;
namespace AutoFixture.TUnit;
@@ -9,7 +9,8 @@ namespace AutoFixture.TUnit;
/// 1. A static property
/// 2. A static field
/// 3. A static method (with parameters)
-/// The member must return something compatible with IEnumerable<object?[]> with the test data.
+/// The member must return test data in any shape supported by TUnit MethodDataSource
+/// (for example IEnumerable<object?[]>, IEnumerable<T>, tuples, or a single value).
///
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
Justification = "This attribute is the root of a potential attribute hierarchy.")]
@@ -59,7 +60,7 @@ protected AutoMemberDataSourceAttribute(Func fixtureFactory, Type? mem
{
this.FixtureFactory = fixtureFactory ?? throw new ArgumentNullException(nameof(fixtureFactory));
this.MemberName = memberName ?? throw new ArgumentNullException(nameof(memberName));
- this.Parameters = parameters ?? [null!];
+ this.Parameters = parameters ?? [null];
this.MemberType = memberType;
}
@@ -86,12 +87,8 @@ protected AutoMemberDataSourceAttribute(Func fixtureFactory, Type? mem
///
public override IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata)
{
- var testMethod = dataGeneratorMetadata.GetMethod();
-
- if (testMethod is null)
- {
- throw new ArgumentNullException(nameof(dataGeneratorMetadata), "The test method cannot be null.");
- }
+ var testMethod = dataGeneratorMetadata.GetMethod()
+ ?? throw new ArgumentNullException(nameof(dataGeneratorMetadata), "The test method cannot be null.");
var sourceType = this.MemberType ?? testMethod.DeclaringType
?? throw new InvalidOperationException("Source type cannot be null.");
@@ -102,4 +99,4 @@ protected AutoMemberDataSourceAttribute(Func fixtureFactory, Type? mem
return source.GetDataRowsAsync(dataGeneratorMetadata);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute{T}.cs b/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute{T}.cs
new file mode 100644
index 0000000..0db0aba
--- /dev/null
+++ b/src/AutoFixture.TUnit/AutoMemberDataSourceAttribute{T}.cs
@@ -0,0 +1,38 @@
+using System.Diagnostics.CodeAnalysis;
+
+namespace AutoFixture.TUnit;
+
+///
+/// Generic form of that takes the member-declaring type
+/// as a type argument instead of .
+///
+/// The type that declares the static member providing test data.
+///
+/// Requires C# 11 or later to use the [AutoMemberDataSource<T>] attribute syntax.
+///
+[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
+ Justification = "This attribute is the root of a potential attribute hierarchy.")]
+public class AutoMemberDataSourceAttribute : AutoMemberDataSourceAttribute
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name of the public static member on that will provide the test data.
+ /// The parameters for the member (only supported for methods; ignored for everything else).
+ public AutoMemberDataSourceAttribute(string memberName, params object?[] parameters)
+ : base(typeof(T), memberName, parameters)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// with a custom fixture factory.
+ ///
+ /// The fixture factory delegate.
+ /// The name of the public static member on that will provide the test data.
+ /// The parameters for the member (only supported for methods; ignored for everything else).
+ protected AutoMemberDataSourceAttribute(Func fixtureFactory, string memberName, params object?[] parameters)
+ : base(fixtureFactory, typeof(T), memberName, parameters)
+ {
+ }
+}
diff --git a/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs b/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs
index 39d8fc6..c05205c 100644
--- a/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs
+++ b/src/AutoFixture.TUnit/BaseDataSourceAttribute.cs
@@ -1,4 +1,4 @@
-using AutoFixture.TUnit.Internal;
+using AutoFixture.TUnit.Internal;
namespace AutoFixture.TUnit;
@@ -23,6 +23,9 @@ public abstract class BaseDataSourceAttribute : Attribute, IDataSourceAttribute,
///
public bool SkipIfEmpty { get; set; }
+ ///
+ public bool DeferEnumeration { get; set; }
+
///
public async IAsyncEnumerable>> GetDataRowsAsync(DataGeneratorMetadata dataGeneratorMetadata)
{
@@ -32,7 +35,7 @@ public abstract class BaseDataSourceAttribute : Attribute, IDataSourceAttribute,
if (parameters.Length == 0)
{
// If the method has no parameters, a single test run is enough.
- yield return () => Task.FromResult(Array.Empty());
+ yield return () => Task.FromResult([]);
yield break;
}
diff --git a/src/AutoFixture.TUnit/CompositeDataSourceAttribute.cs b/src/AutoFixture.TUnit/CompositeDataSourceAttribute.cs
index 97c8e0f..2523b98 100644
--- a/src/AutoFixture.TUnit/CompositeDataSourceAttribute.cs
+++ b/src/AutoFixture.TUnit/CompositeDataSourceAttribute.cs
@@ -1,4 +1,4 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
using AutoFixture.TUnit.Internal;
namespace AutoFixture.TUnit;
@@ -65,4 +65,4 @@ public CompositeDataSourceAttribute(params BaseDataSourceAttribute[] attributes)
yield return () => Task.FromResult(row);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/CustomizeAttribute.cs b/src/AutoFixture.TUnit/CustomizeAttribute.cs
index 57f6f67..62bba45 100644
--- a/src/AutoFixture.TUnit/CustomizeAttribute.cs
+++ b/src/AutoFixture.TUnit/CustomizeAttribute.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
+using System.Reflection;
namespace AutoFixture.TUnit;
@@ -15,4 +15,4 @@ public abstract class CustomizeAttribute : Attribute, IParameterCustomizationSou
/// The parameter for which the customization is requested.
/// A customization for the parameter.
public abstract ICustomization GetCustomization(ParameterInfo parameter);
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/FavorArraysAttribute.cs b/src/AutoFixture.TUnit/FavorArraysAttribute.cs
index d5eece8..24dd83d 100644
--- a/src/AutoFixture.TUnit/FavorArraysAttribute.cs
+++ b/src/AutoFixture.TUnit/FavorArraysAttribute.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
+using System.Reflection;
using AutoFixture.Kernel;
namespace AutoFixture.TUnit;
@@ -26,4 +26,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter)
return new ConstructorCustomization(parameter.ParameterType, new ArrayFavoringConstructorQuery());
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/FavorEnumerablesAttribute.cs b/src/AutoFixture.TUnit/FavorEnumerablesAttribute.cs
index d19dbb4..7ee0b29 100644
--- a/src/AutoFixture.TUnit/FavorEnumerablesAttribute.cs
+++ b/src/AutoFixture.TUnit/FavorEnumerablesAttribute.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
+using System.Reflection;
using AutoFixture.Kernel;
namespace AutoFixture.TUnit;
@@ -26,4 +26,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter)
return new ConstructorCustomization(parameter.ParameterType, new EnumerableFavoringConstructorQuery());
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/FavorListsAttribute.cs b/src/AutoFixture.TUnit/FavorListsAttribute.cs
index 0b497d9..45da169 100644
--- a/src/AutoFixture.TUnit/FavorListsAttribute.cs
+++ b/src/AutoFixture.TUnit/FavorListsAttribute.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
+using System.Reflection;
using AutoFixture.Kernel;
namespace AutoFixture.TUnit;
@@ -26,4 +26,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter)
return new ConstructorCustomization(parameter.ParameterType, new ListFavoringConstructorQuery());
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/FrozenAttribute.cs b/src/AutoFixture.TUnit/FrozenAttribute.cs
index 4061cf8..9f8f95f 100644
--- a/src/AutoFixture.TUnit/FrozenAttribute.cs
+++ b/src/AutoFixture.TUnit/FrozenAttribute.cs
@@ -1,4 +1,4 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using AutoFixture.TUnit.Internal;
@@ -66,4 +66,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter)
return new FreezeOnMatchCustomization(parameter, matcher);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/GreedyAttribute.cs b/src/AutoFixture.TUnit/GreedyAttribute.cs
index 9dc31d0..fedf18e 100644
--- a/src/AutoFixture.TUnit/GreedyAttribute.cs
+++ b/src/AutoFixture.TUnit/GreedyAttribute.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
+using System.Reflection;
using AutoFixture.Kernel;
namespace AutoFixture.TUnit;
@@ -26,4 +26,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter)
return new ConstructorCustomization(parameter.ParameterType, new GreedyConstructorQuery());
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/Argument.cs b/src/AutoFixture.TUnit/Internal/Argument.cs
index 67f58e1..08197e4 100644
--- a/src/AutoFixture.TUnit/Internal/Argument.cs
+++ b/src/AutoFixture.TUnit/Internal/Argument.cs
@@ -14,4 +14,4 @@ public Argument(TestParameter parameter, object? value)
public ICustomization GetCustomization()
=> this.Parameter.GetCustomization(this.Value);
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/AutoDataSource.cs b/src/AutoFixture.TUnit/Internal/AutoDataSource.cs
index 00c75c8..4ba50c3 100644
--- a/src/AutoFixture.TUnit/Internal/AutoDataSource.cs
+++ b/src/AutoFixture.TUnit/Internal/AutoDataSource.cs
@@ -45,7 +45,8 @@ public AutoDataSource(Func createFixture, IDataSource? source = null)
{
var parameters = Array.ConvertAll(metadata.GetMethod().GetParameters(), TestParameter.From);
var fixture = this.CreateFixture();
- return new[] { Array.ConvertAll(parameters, parameter => (object?)GenerateAutoValue(parameter, fixture)) }.ToAsyncDataSource();
+ object[][] rows = [Array.ConvertAll(parameters, parameter => GenerateAutoValue(parameter, fixture))];
+ return rows.ToAsyncDataSource();
}
private async IAsyncEnumerable>> CombineValues(DataGeneratorMetadata metadata, IDataSource source)
@@ -56,9 +57,19 @@ public AutoDataSource(Func createFixture, IDataSource? source = null)
await foreach (var testDataFunc in source.GetData(metadata))
{
- var testData = await testDataFunc();
+ if (testDataFunc is null)
+ throw new InvalidOperationException("The source member yielded a null test data.");
- var customizations = parameters.Take(testData!.Length)
+ var testData = await testDataFunc()
+ ?? throw new InvalidOperationException("The source member yielded a null test data.");
+
+ if (testData.Length > parameters.Length)
+ {
+ throw new InvalidOperationException(
+ "The number of arguments provided exceeds the number of parameters.");
+ }
+
+ var customizations = parameters.Take(testData.Length)
.Zip(testData, (parameter, value) => new Argument(parameter, value))
.Select(argument => argument.GetCustomization())
.Where(x => x is not NullCustomization);
@@ -90,4 +101,4 @@ private static object GenerateAutoValue(TestParameter parameter, IFixture fixtur
return fixture.Resolve(parameter.ParameterInfo);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/ClassDataSource.cs b/src/AutoFixture.TUnit/Internal/ClassDataSource.cs
index 2b194f8..42e7612 100644
--- a/src/AutoFixture.TUnit/Internal/ClassDataSource.cs
+++ b/src/AutoFixture.TUnit/Internal/ClassDataSource.cs
@@ -1,4 +1,4 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
namespace AutoFixture.TUnit.Internal;
@@ -37,12 +37,6 @@ public ClassDataSource(Type type, params object?[] parameters)
public override IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata)
{
var instance = Activator.CreateInstance(type: this.Type, args: this.parameters);
-
- if (instance is not IEnumerable enumerable)
- {
- throw new InvalidOperationException($"Data source type \"{this.Type}\" should implement the \"{typeof(IEnumerable)}\" interface.");
- }
-
- return enumerable.ToAsyncDataSource();
+ return ToAsyncDataRows(instance);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/CustomizationExtensions.cs b/src/AutoFixture.TUnit/Internal/CustomizationExtensions.cs
index b447722..5ded7c8 100644
--- a/src/AutoFixture.TUnit/Internal/CustomizationExtensions.cs
+++ b/src/AutoFixture.TUnit/Internal/CustomizationExtensions.cs
@@ -6,4 +6,4 @@ internal static class CustomizationExtensions
{
public static object Resolve(this IFixture source, object request)
=> new SpecimenContext(source).Resolve(request);
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/CustomizeAttributeComparer.cs b/src/AutoFixture.TUnit/Internal/CustomizeAttributeComparer.cs
index 0303179..2f979ed 100644
--- a/src/AutoFixture.TUnit/Internal/CustomizeAttributeComparer.cs
+++ b/src/AutoFixture.TUnit/Internal/CustomizeAttributeComparer.cs
@@ -1,4 +1,4 @@
-namespace AutoFixture.TUnit.Internal;
+namespace AutoFixture.TUnit.Internal;
internal sealed class CustomizeAttributeComparer : Comparer
{
@@ -11,4 +11,4 @@ public override int Compare(IParameterCustomizationSource? x, IParameterCustomiz
_ => 0
};
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/DataGeneratorMetadataExtensions.cs b/src/AutoFixture.TUnit/Internal/DataGeneratorMetadataExtensions.cs
index 96e7d9c..4a55ab5 100644
--- a/src/AutoFixture.TUnit/Internal/DataGeneratorMetadataExtensions.cs
+++ b/src/AutoFixture.TUnit/Internal/DataGeneratorMetadataExtensions.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
+using System.Reflection;
using TUnit.Core.Enums;
using TUnit.Core.Extensions;
@@ -8,16 +8,46 @@ internal static class DataGeneratorMetadataExtensions
{
public static MethodBase GetMethod(this DataGeneratorMetadata dataGeneratorMetadata)
{
- if (dataGeneratorMetadata.TestInformation == null)
+ if (dataGeneratorMetadata.TestInformation is null)
{
throw new InvalidOperationException("Not a test method");
}
-
+
if (dataGeneratorMetadata.Type == DataGeneratorType.ClassParameters)
{
- return dataGeneratorMetadata.TestInformation.Class.Type.GetConstructors().First();
+ var constructors = dataGeneratorMetadata.TestInformation.Class.Type.GetConstructors();
+ var members = dataGeneratorMetadata.MembersToGenerate;
+
+ return constructors.FirstOrDefault(constructor => MatchesMembers(constructor, members))
+ ?? throw new InvalidOperationException(
+ "Could not find a constructor matching the class parameters to generate.");
}
return dataGeneratorMetadata.TestInformation.GetReflectionInfo();
}
-}
\ No newline at end of file
+
+ private static bool MatchesMembers(ConstructorInfo constructor, IMemberMetadata[] members)
+ {
+ var parameters = constructor.GetParameters();
+ if (parameters.Length != members.Length)
+ {
+ return false;
+ }
+
+ for (var i = 0; i < parameters.Length; i++)
+ {
+ if (members[i] is not ParameterMetadata parameterMetadata)
+ {
+ return false;
+ }
+
+ if (parameters[i].ParameterType != parameterMetadata.Type
+ || !string.Equals(parameters[i].Name, parameterMetadata.Name, StringComparison.Ordinal))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/src/AutoFixture.TUnit/Internal/DataSource.cs b/src/AutoFixture.TUnit/Internal/DataSource.cs
index a7cd44b..d620062 100644
--- a/src/AutoFixture.TUnit/Internal/DataSource.cs
+++ b/src/AutoFixture.TUnit/Internal/DataSource.cs
@@ -1,4 +1,7 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Collections;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using TUnit.Core.Helpers;
namespace AutoFixture.TUnit.Internal;
@@ -9,4 +12,126 @@ namespace AutoFixture.TUnit.Internal;
Justification = "The type is not a collection.")]
[SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix",
Justification = "The type is not a collection.")]
-public abstract class DataSource : BaseDataSourceAttribute;
\ No newline at end of file
+public abstract class DataSource : BaseDataSourceAttribute
+{
+ ///
+ /// Converts a TUnit-compatible data source result into async row factories.
+ ///
+ ///
+ /// The raw data source result (for example a sequence, tuple, scalar, task, or async enumerable).
+ ///
+ ///
+ /// A token used to cancel async enumeration of the data rows.
+ ///
+ ///
+ /// An asynchronous sequence of factories that each produce one object?[] test case row.
+ ///
+ protected static async IAsyncEnumerable>> ToAsyncDataRows(
+ object? value,
+ [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ {
+ while (value is Task task)
+ {
+ await task.ConfigureAwait(false);
+ value = GetTaskResult(task);
+ }
+
+ if (value is null)
+ {
+ yield return static () => Task.FromResult([null]);
+ yield break;
+ }
+
+ if (TryGetAsyncElementType(value, out var elementType))
+ {
+ var convert = typeof(DataConversionHelper)
+ .GetMethod(nameof(DataConversionHelper.ConvertAsyncEnumerableToObjectArrays))!
+ .MakeGenericMethod(elementType);
+
+ var rows = (IAsyncEnumerable)convert
+ .Invoke(null, [value, cancellationToken])!;
+
+ await foreach (var row in rows.WithCancellation(cancellationToken).ConfigureAwait(false))
+ {
+ var captured = ExpandCollapsedRow(row);
+ yield return () => Task.FromResult(captured);
+ }
+
+ yield break;
+ }
+
+ if (IsRowSequence(value))
+ {
+ foreach (var row in DataConversionHelper.ConvertToObjectArrays(value))
+ {
+ var captured = ExpandCollapsedRow(row);
+ yield return () => Task.FromResult(captured);
+ }
+
+ yield break;
+ }
+
+ var singleRow = DataSourceHelpers.ToObjectArray(value);
+ yield return () => Task.FromResult(singleRow);
+ }
+
+ // TUnit Convert*ToObjectArrays can leave a ValueTuple or object[] as one cell.
+ private static object?[] ExpandCollapsedRow(object?[] row)
+ {
+ if (row is not [var only])
+ {
+ return row;
+ }
+
+ if (DataSourceHelpers.IsTuple(only))
+ {
+ return DataSourceHelpers.ToObjectArray(only);
+ }
+
+ if (only is object[] alreadyRow)
+ {
+ return alreadyRow;
+ }
+
+ return row;
+ }
+
+ private static object? GetTaskResult(Task task)
+ {
+ var resultProperty = task.GetType().GetProperty("Result");
+ return resultProperty?.GetValue(task);
+ }
+
+ private static bool IsRowSequence(object value)
+ {
+ if (value is string)
+ {
+ return false;
+ }
+
+ if (DataSourceHelpers.IsTuple(value))
+ {
+ return false;
+ }
+
+ return value is IEnumerable;
+ }
+
+ private static bool TryGetAsyncElementType(object value, out Type elementType)
+ {
+ var asyncEnumerable = (
+ from type in value.GetType().GetInterfaces()
+ where type.IsGenericType
+ && type.GetGenericTypeDefinition() == typeof(IAsyncEnumerable<>)
+ select type).FirstOrDefault();
+
+ if (asyncEnumerable is null)
+ {
+ elementType = null!;
+ return false;
+ }
+
+ elementType = asyncEnumerable.GetGenericArguments()[0];
+ return true;
+ }
+}
diff --git a/src/AutoFixture.TUnit/Internal/EnumerableExtensions.cs b/src/AutoFixture.TUnit/Internal/EnumerableExtensions.cs
index 81c218c..46a12cc 100644
--- a/src/AutoFixture.TUnit/Internal/EnumerableExtensions.cs
+++ b/src/AutoFixture.TUnit/Internal/EnumerableExtensions.cs
@@ -1,4 +1,4 @@
-namespace AutoFixture.TUnit.Internal;
+namespace AutoFixture.TUnit.Internal;
internal static class EnumerableExtensions
{
@@ -41,9 +41,8 @@ internal static IEnumerable Collapse(this IEnumerable> sequ
}
}
- #pragma warning disable CS1998 // Async method lacks 'await' - required for IAsyncEnumerable yield
+#pragma warning disable CS1998 // Async method lacks 'await' - required for IAsyncEnumerable yield
internal static async IAsyncEnumerable>> ToAsyncDataSource(
- #pragma warning restore CS1998
this IEnumerable source)
{
foreach (var item in source)
@@ -51,4 +50,5 @@ internal static IEnumerable Collapse(this IEnumerable> sequ
yield return () => Task.FromResult(item);
}
}
-}
\ No newline at end of file
+#pragma warning restore CS1998
+}
diff --git a/src/AutoFixture.TUnit/Internal/FieldDataSource.cs b/src/AutoFixture.TUnit/Internal/FieldDataSource.cs
index 9784b2d..df2ecfe 100644
--- a/src/AutoFixture.TUnit/Internal/FieldDataSource.cs
+++ b/src/AutoFixture.TUnit/Internal/FieldDataSource.cs
@@ -31,18 +31,9 @@ public FieldDataSource(FieldInfo fieldInfo)
/// Gets the test data from the source field.
///
/// Returns a sequence of argument collections.
- ///
- /// Thrown when the field does not return an enumerable value.
- ///
public override IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata)
{
var value = this.FieldInfo.GetValue(null);
-
- if (value is not IEnumerable enumerable)
- {
- throw new InvalidCastException("Member does not return an enumerable value.");
- }
-
- return enumerable.ToAsyncDataSource();
+ return ToAsyncDataRows(value);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/FrozenValueCustomization.cs b/src/AutoFixture.TUnit/Internal/FrozenValueCustomization.cs
index 4717352..1a00323 100644
--- a/src/AutoFixture.TUnit/Internal/FrozenValueCustomization.cs
+++ b/src/AutoFixture.TUnit/Internal/FrozenValueCustomization.cs
@@ -21,4 +21,4 @@ public void Customize(IFixture fixture)
fixture.Customizations.Insert(0, builder);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/IDataSource.cs b/src/AutoFixture.TUnit/Internal/IDataSource.cs
index aea9f87..1fba501 100644
--- a/src/AutoFixture.TUnit/Internal/IDataSource.cs
+++ b/src/AutoFixture.TUnit/Internal/IDataSource.cs
@@ -1,4 +1,4 @@
-namespace AutoFixture.TUnit.Internal;
+namespace AutoFixture.TUnit.Internal;
///
/// Exposes the factory method for a sequence of test data.
@@ -11,4 +11,4 @@ public interface IDataSource
/// The target method for which to provide the arguments.
/// Returns a sequence of argument collections.
IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata);
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/InlineDataSource.cs b/src/AutoFixture.TUnit/Internal/InlineDataSource.cs
index a59f1d8..88eeed9 100644
--- a/src/AutoFixture.TUnit/Internal/InlineDataSource.cs
+++ b/src/AutoFixture.TUnit/Internal/InlineDataSource.cs
@@ -29,9 +29,9 @@ public InlineDataSource(object?[] values)
public IReadOnlyList Values => Array.AsReadOnly(this.values);
///
- #pragma warning disable CS1998 // Async method lacks 'await' - required for IAsyncEnumerable yield
+#pragma warning disable CS1998 // Async method lacks 'await' - required for IAsyncEnumerable yield
public override async IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata)
- #pragma warning restore CS1998
+#pragma warning restore CS1998
{
if (dataGeneratorMetadata is null)
{
@@ -47,4 +47,4 @@ public InlineDataSource(object?[] values)
yield return () => Task.FromResult(this.values);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/MemberDataSource.cs b/src/AutoFixture.TUnit/Internal/MemberDataSource.cs
index e8ded91..6823f96 100644
--- a/src/AutoFixture.TUnit/Internal/MemberDataSource.cs
+++ b/src/AutoFixture.TUnit/Internal/MemberDataSource.cs
@@ -60,15 +60,6 @@ private DataSource GetTestDataSource()
throw new ArgumentException(message);
}
- var returnType = sourceMember.GetReturnType();
- if (!typeof(IEnumerable).IsAssignableFrom(returnType))
- {
- var message = string.Format(
- CultureInfo.CurrentCulture,
- "Member {0} on {1} does not return IEnumerable", this.Name, this.Type.FullName);
- throw new ArgumentException(message);
- }
-
return sourceMember switch
{
FieldInfo fieldInfo => new FieldDataSource(fieldInfo),
@@ -83,4 +74,4 @@ private DataSource GetTestDataSource()
{
return this.Source.GetDataRowsAsync(dataGeneratorMetadata);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/MethodDataSource.cs b/src/AutoFixture.TUnit/Internal/MethodDataSource.cs
index 91a6221..9a852b8 100644
--- a/src/AutoFixture.TUnit/Internal/MethodDataSource.cs
+++ b/src/AutoFixture.TUnit/Internal/MethodDataSource.cs
@@ -37,12 +37,6 @@ public MethodDataSource(MethodInfo methodInfo, params object?[] arguments)
public override IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata)
{
var value = this.MethodInfo.Invoke(null, this.arguments);
-
- if (value is not IEnumerable enumerable)
- {
- throw new InvalidCastException("Member does not return an enumerable value.");
- }
-
- return enumerable.ToAsyncDataSource();
+ return ToAsyncDataRows(value);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/NullCustomization.cs b/src/AutoFixture.TUnit/Internal/NullCustomization.cs
index 18b2b09..afb3fd0 100644
--- a/src/AutoFixture.TUnit/Internal/NullCustomization.cs
+++ b/src/AutoFixture.TUnit/Internal/NullCustomization.cs
@@ -16,4 +16,4 @@ public void Customize(IFixture fixture)
{
// intentionally left blank
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/ParameterFilter.cs b/src/AutoFixture.TUnit/Internal/ParameterFilter.cs
index 1a15d59..9310c1b 100644
--- a/src/AutoFixture.TUnit/Internal/ParameterFilter.cs
+++ b/src/AutoFixture.TUnit/Internal/ParameterFilter.cs
@@ -39,4 +39,4 @@ public bool IsSatisfiedBy(object request)
{
return this.matcherSpecification.IsSatisfiedBy(request);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/ParameterMatcherBuilder.cs b/src/AutoFixture.TUnit/Internal/ParameterMatcherBuilder.cs
index faf4e02..e3833ba 100644
--- a/src/AutoFixture.TUnit/Internal/ParameterMatcherBuilder.cs
+++ b/src/AutoFixture.TUnit/Internal/ParameterMatcherBuilder.cs
@@ -195,4 +195,4 @@ public bool Equals(Type? x, Type? y)
public int GetHashCode(Type obj) => 0;
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/PropertyDataSource.cs b/src/AutoFixture.TUnit/Internal/PropertyDataSource.cs
index f6ee139..f303cc5 100644
--- a/src/AutoFixture.TUnit/Internal/PropertyDataSource.cs
+++ b/src/AutoFixture.TUnit/Internal/PropertyDataSource.cs
@@ -29,12 +29,6 @@ public PropertyDataSource(PropertyInfo propertyInfo)
public override IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata)
{
var value = this.PropertyInfo.GetValue(null);
-
- if (value is not IEnumerable enumerable)
- {
- throw new InvalidCastException("Member does not return an enumerable value.");
- }
-
- return enumerable.ToAsyncDataSource();
+ return ToAsyncDataRows(value);
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Internal/ReflectionExtensions.cs b/src/AutoFixture.TUnit/Internal/ReflectionExtensions.cs
deleted file mode 100644
index 213b173..0000000
--- a/src/AutoFixture.TUnit/Internal/ReflectionExtensions.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System.Reflection;
-
-namespace AutoFixture.TUnit.Internal;
-
-internal static class ReflectionExtensions
-{
- public static Type GetReturnType(this MemberInfo member)
- {
- if (member is null)
- {
- throw new ArgumentNullException(nameof(member));
- }
-
- return member switch
- {
- MethodInfo methodInfo => methodInfo.ReturnType,
- PropertyInfo propertyInfo => propertyInfo.PropertyType,
- FieldInfo fieldInfo => fieldInfo.FieldType,
- _ => throw new ArgumentException("Member is not a method, property, or field.", nameof(member))
- };
- }
-}
\ No newline at end of file
diff --git a/src/AutoFixture.TUnit/Internal/TestParameter.cs b/src/AutoFixture.TUnit/Internal/TestParameter.cs
index 0509b0b..6690382 100644
--- a/src/AutoFixture.TUnit/Internal/TestParameter.cs
+++ b/src/AutoFixture.TUnit/Internal/TestParameter.cs
@@ -52,4 +52,4 @@ private static ICustomization GetCustomization(ParameterInfo parameter)
}
public static TestParameter From(ParameterInfo parameterInfo) => new(parameterInfo);
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/Matching.cs b/src/AutoFixture.TUnit/Matching.cs
index e284d4a..911e95e 100644
--- a/src/AutoFixture.TUnit/Matching.cs
+++ b/src/AutoFixture.TUnit/Matching.cs
@@ -1,4 +1,4 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
namespace AutoFixture.TUnit;
@@ -58,4 +58,4 @@ public enum Matching
/// and has a specific name.
///
MemberName = ParameterName | PropertyName | FieldName
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/ModestAttribute.cs b/src/AutoFixture.TUnit/ModestAttribute.cs
index a1fa8ba..844e37b 100644
--- a/src/AutoFixture.TUnit/ModestAttribute.cs
+++ b/src/AutoFixture.TUnit/ModestAttribute.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
+using System.Reflection;
using AutoFixture.Kernel;
namespace AutoFixture.TUnit;
@@ -26,4 +26,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter)
return new ConstructorCustomization(parameter.ParameterType, new ModestConstructorQuery());
}
-}
\ No newline at end of file
+}
diff --git a/src/AutoFixture.TUnit/NoAutoPropertiesAttribute.cs b/src/AutoFixture.TUnit/NoAutoPropertiesAttribute.cs
index b8039f9..ece786d 100644
--- a/src/AutoFixture.TUnit/NoAutoPropertiesAttribute.cs
+++ b/src/AutoFixture.TUnit/NoAutoPropertiesAttribute.cs
@@ -1,4 +1,4 @@
-using System.Reflection;
+using System.Reflection;
namespace AutoFixture.TUnit;
@@ -27,4 +27,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter)
var targetType = parameter.ParameterType;
return new NoAutoPropertiesCustomization(targetType);
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs
new file mode 100644
index 0000000..83f7174
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ArrayEdgeCaseScenarioTests.cs
@@ -0,0 +1,43 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests;
+
+///
+/// Documents the params object?[] pitfall: a non-generic
+/// [AutoArguments([ ... ])] expands into separate cells,
+/// while [AutoArguments<T[]>(...)] keeps the array as one argument.
+///
+public class ArrayEdgeCaseScenarioTests
+{
+ [Test]
+ [AutoArguments([1, 2])]
+ public async Task WhenNonGenericObjectArray_ExpandsIntoSeparateArguments(int a, int b)
+ {
+ await Assert.That(a).IsEqualTo(1);
+ await Assert.That(b).IsEqualTo(2);
+ }
+
+ [Test]
+ [AutoArguments([1, 2])]
+ public async Task WhenGenericObjectArray_KeepsArrayAsSingleArgument(object[] values, MyClass leftover)
+ {
+ await Assert.That(values).IsEquivalentTo([1, 2]);
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoArguments([1, 2])]
+ public async Task WhenGenericIntArray_KeepsArrayAsSingleArgument(int[] values, MyClass leftover)
+ {
+ await Assert.That(values).IsEquivalentTo([1, 2]);
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoArguments(["a", "b"])]
+ public async Task WhenGenericStringArray_KeepsArrayAsSingleArgument(string[] values, MyClass leftover)
+ {
+ await Assert.That(values).IsEquivalentTo(["a", "b"]);
+ await Assert.That(leftover).IsNotNull();
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ClassLevelScenarioTests.cs
new file mode 100644
index 0000000..2b3d16e
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ClassLevelScenarioTests.cs
@@ -0,0 +1,112 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+using ConcreteType = TestTypeFoundation.ConcreteType;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests;
+
+///
+/// End-to-end [AutoArguments] on the test class (TUnit ClassParameters).
+/// Ordered simple → complex; mirrors AutoDataSource class-level scenarios.
+///
+[AutoArguments("seed")]
+public class ClassLevelPrimitiveScenarioTests(string name, int count)
+{
+ [Test]
+ public async Task WhenAppliedToClass_UsesInlineValueAndFillsRemaining()
+ {
+ await Assert.That(name).IsEqualTo("seed");
+ await Assert.That(count).IsNotEqualTo(0);
+ }
+}
+
+[AutoArguments("seed")]
+public class ClassLevelComplexTypeScenarioTests(
+ string name,
+ PropertyHolder ph,
+ SingleParameterType spt,
+ MyClass sut)
+{
+ [Test]
+ public async Task WhenAppliedToClass_UsesInlineValueAndFillsComplexRemaining()
+ {
+ await Assert.That(name).IsEqualTo("seed");
+
+ await Assert.That(ph).IsNotNull();
+ await Assert.That(ph.Property).IsNotNull();
+
+ await Assert.That(spt).IsNotNull();
+ await Assert.That(spt.Parameter).IsNotNull();
+
+ await Assert.That(sut).IsNotNull();
+ await Assert.That(sut.Echo(7)).IsEqualTo(7);
+ }
+}
+
+[AutoArguments]
+public class ClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second)
+{
+ [Test]
+ public async Task WhenFrozenOnConstructorParameter_SharesInstanceWithLaterParameter()
+ {
+ await Assert.That(second).IsEqualTo(first);
+ }
+}
+
+[AutoArguments]
+public class ClassLevelModestScenarioTests([Modest] MultiUnorderedConstructorType value)
+{
+ [Test]
+ public async Task WhenModestOnConstructorParameter_UsesModestConstructor()
+ {
+ await Assert.That(string.IsNullOrEmpty(value.Text)).IsTrue();
+ await Assert.That(value.Number).IsEqualTo(0);
+ }
+}
+
+[AutoArguments("from-inline")]
+public class ClassLevelMultiConstructorParameterizedFirstScenarioTests
+{
+ private readonly string name;
+
+ public ClassLevelMultiConstructorParameterizedFirstScenarioTests(string name)
+ {
+ this.name = name;
+ }
+
+ public ClassLevelMultiConstructorParameterizedFirstScenarioTests()
+ {
+ this.name = "parameterless";
+ }
+
+ [Test]
+ public async Task WhenParameterizedConstructorDeclaredFirst_UsesInlineConstructorArgument()
+ {
+ await Assert.That(this.name).IsEqualTo("from-inline");
+ }
+}
+
+[AutoArguments(42)]
+public class ClassLevelMultiConstructorIntFirstScenarioTests
+{
+ private readonly string name;
+ private readonly int count;
+
+ public ClassLevelMultiConstructorIntFirstScenarioTests(int count)
+ {
+ this.name = "int-ctor";
+ this.count = count;
+ }
+
+ public ClassLevelMultiConstructorIntFirstScenarioTests(string name)
+ {
+ this.name = name;
+ this.count = -1;
+ }
+
+ [Test]
+ public async Task WhenIntConstructorDeclaredFirst_UsesInlineIntArgument()
+ {
+ await Assert.That(this.name).IsEqualTo("int-ctor");
+ await Assert.That(this.count).IsEqualTo(42);
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericClassLevelScenarioTests.cs
new file mode 100644
index 0000000..11df8af
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericClassLevelScenarioTests.cs
@@ -0,0 +1,53 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+using ConcreteType = TestTypeFoundation.ConcreteType;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests;
+
+///
+/// Class-level [AutoArguments<T>] scenarios parallel to the non-generic class-level set.
+///
+[AutoArguments("seed")]
+public class GenericClassLevelPrimitiveScenarioTests(string name, int count)
+{
+ [Test]
+ public async Task WhenGenericAppliedToClass_UsesInlineValueAndFillsRemaining()
+ {
+ await Assert.That(name).IsEqualTo("seed");
+ await Assert.That(count).IsNotEqualTo(0);
+ }
+}
+
+[AutoArguments("seed")]
+public class GenericClassLevelComplexTypeScenarioTests(
+ string name,
+ PropertyHolder ph,
+ SingleParameterType spt,
+ MyClass sut)
+{
+ [Test]
+ public async Task WhenGenericAppliedToClass_UsesInlineValueAndFillsComplexRemaining()
+ {
+ await Assert.That(name).IsEqualTo("seed");
+
+ await Assert.That(ph).IsNotNull();
+ await Assert.That(ph.Property).IsNotNull();
+
+ await Assert.That(spt).IsNotNull();
+ await Assert.That(spt.Parameter).IsNotNull();
+
+ await Assert.That(sut).IsNotNull();
+ await Assert.That(sut.Echo(7)).IsEqualTo(7);
+ }
+}
+
+[AutoArguments("seed")]
+public class GenericClassLevelFrozenScenarioTests(string name, [Frozen] Guid first, Guid second)
+{
+ [Test]
+ public async Task WhenGenericFrozenOnConstructorParameter_SharesInstanceWithLaterParameter()
+ {
+ await Assert.That(name).IsEqualTo("seed");
+ await Assert.That(second).IsEqualTo(first);
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericUsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericUsageScenarioTests.cs
new file mode 100644
index 0000000..285400d
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GenericUsageScenarioTests.cs
@@ -0,0 +1,62 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests;
+
+///
+/// End-to-end [AutoArguments<T>] usage parallel to the non-generic scenarios.
+///
+public class GenericUsageScenarioTests
+{
+ [Test]
+ [AutoArguments("foo")]
+ public async Task WhenGenericInlineValueProvided_UsesSuppliedValueAndFillsRemaining(string s1, string s2)
+ {
+ await Assert.That(s1).IsEqualTo("foo");
+ await Assert.That(s2).IsNotNull();
+ }
+
+ [Test]
+ [AutoArguments("foo")]
+ public async Task WhenGenericInlineValuePartial_SuppliesRemainingSpecimens(
+ string s1, string s2, MyClass myClass)
+ {
+ await Assert.That(s1).IsEqualTo("foo");
+ await Assert.That(s2).IsNotNull();
+ await Assert.That(myClass).IsNotNull();
+ }
+
+ [Test]
+ [AutoArguments("foo")]
+ public async Task WhenGenericInlineValuePartial_DoesNotOverwriteSuppliedValue(
+ string s1, string s2, string s3)
+ {
+ await Assert.That(s1).IsEqualTo("foo");
+ await Assert.That(s2).IsNotNull();
+ await Assert.That(s3).IsNotEqualTo("foo");
+ }
+
+ [Test]
+ [MyCustomAutoArguments(1337)]
+ public async Task WhenGenericCustomInlineAttribute_SuppliesExtraValues(int x, int y, int z)
+ {
+ await Assert.That(x).IsEqualTo(1337);
+ await Assert.That(y).IsNotEqualTo(0);
+ await Assert.That(z).IsEqualTo(42);
+ }
+
+ public class MyCustomAutoArgumentsAttribute : AutoArgumentsAttribute
+ {
+ public MyCustomAutoArgumentsAttribute(T value)
+ : base(() => new Fixture().Customize(new TheAnswer()), value)
+ {
+ }
+ }
+
+ private class TheAnswer : ICustomization
+ {
+ public void Customize(IFixture fixture)
+ {
+ fixture.Inject(42);
+ }
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/AutoArgumentsAttributeTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GetDataTests.cs
similarity index 76%
rename from tests/AutoFixture.TUnit.Tests/AutoArgumentsAttributeTests.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GetDataTests.cs
index 9714b8d..ed6a09a 100644
--- a/tests/AutoFixture.TUnit.Tests/AutoArgumentsAttributeTests.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/GetDataTests.cs
@@ -1,13 +1,14 @@
-using System.Reflection;
+using System.Reflection;
+using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport;
using AutoFixture.TUnit.Tests.TestTypes;
using TestTypeFoundation;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests;
public class AutoArgumentsAttributeTests
{
[Test]
- public async Task SutIsDataAttribute()
+ public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute()
{
// Arrange & Act
var sut = new AutoArgumentsAttribute();
@@ -17,7 +18,7 @@ public async Task SutIsDataAttribute()
}
[Test]
- public async Task ValuesWillBeEmptyWhenSutIsCreatedWithDefaultConstructor()
+ public async Task Constructor_WhenDefault_ValuesAreEmpty()
{
// Arrange
var sut = new AutoArgumentsAttribute();
@@ -31,10 +32,10 @@ public async Task ValuesWillBeEmptyWhenSutIsCreatedWithDefaultConstructor()
}
[Test]
- public async Task ValuesWillNotBeEmptyWhenSutIsCreatedWithConstructorArguments()
+ public async Task Constructor_WhenArgumentsProvided_ValuesAreNotEmpty()
{
// Arrange
- var expectedValues = new[] { new object(), new object(), new object() };
+ object[] expectedValues = [new object(), new object(), new object()];
var sut = new AutoArgumentsAttribute(expectedValues);
// Act
@@ -45,10 +46,10 @@ public async Task ValuesWillNotBeEmptyWhenSutIsCreatedWithConstructorArguments()
}
[Test]
- public async Task ValuesAreCorrectWhenConstructedWithExplicitAutoDataAttribute()
+ public async Task Constructor_WhenExplicitValuesProvided_ValuesMatch()
{
// Arrange
- var expectedValues = new[] { new object(), new object(), new object() };
+ object[] expectedValues = [new object(), new object(), new object()];
var sut = new DerivedAutoArgumentsAttribute(() => new DelegatingFixture(), expectedValues);
// Act
@@ -59,7 +60,7 @@ public async Task ValuesAreCorrectWhenConstructedWithExplicitAutoDataAttribute()
}
[Test]
- public async Task DoesntActivateFixtureImmediately()
+ public async Task Constructor_WhenCreated_DoesNotActivateFixtureImmediately()
{
// Arrange
var wasInvoked = false;
@@ -88,7 +89,7 @@ public async Task DoesntActivateFixtureImmediately()
[Arguments("CreateWithModestAndFrozen")]
[Arguments("CreateWithFrozenAndNoAutoProperties")]
[Arguments("CreateWithNoAutoPropertiesAndFrozen")]
- public async Task GetDataOrdersCustomizationAttributes(string methodName)
+ public async Task GetData_WhenCustomizationsPresent_OrdersThem(string methodName)
{
// Arrange
var customizationLog = new List();
@@ -115,7 +116,7 @@ public async Task GetDataOrdersCustomizationAttributes(string methodName)
[Test]
[MethodDataSource(typeof(InlinePrimitiveValuesTestData), nameof(InlinePrimitiveValuesTestData.GetTestData))]
[MethodDataSource(typeof(InlineFrozenValuesTestData), nameof(InlineFrozenValuesTestData.GetTestData))]
- public async Task ReturnsSingleTestDataWithExpectedValues(BaseDataSourceAttribute attribute, MethodInfo testMethod,
+ public async Task GetData_WhenCalled_ReturnsSingleRowWithExpectedValues(BaseDataSourceAttribute attribute, MethodInfo testMethod,
object[] expected)
{
// Act
@@ -128,17 +129,17 @@ public async Task ReturnsSingleTestDataWithExpectedValues(BaseDataSourceAttribut
[Test]
[AutoArguments]
- public async Task GeneratesRandomData(int a, float b, string c, decimal d)
+ public async Task WhenAutoArgumentsUsed_GeneratesNonDefaultValues(int a, float b, string c, decimal d)
{
await Assert.That(a).IsNotEqualTo(0);
- await Assert.That(b).IsNotEqualTo(0);
+ await Assert.That(b).IsNotEqualTo(0f);
await Assert.That(c).IsNotNull();
- await Assert.That(d).IsNotEqualTo(0);
+ await Assert.That(d).IsNotEqualTo(0m);
}
[Test]
[AutoArguments(12, 32.1f, "hello", 71.231d)]
- public async Task InlinesAllData(int a, float b, string c, decimal d)
+ public async Task WhenInlineValuesProvided_UsesAllSuppliedValues(int a, float b, string c, decimal d)
{
await Assert.That(a).IsEqualTo(12);
await Assert.That(b).IsEqualTo(32.1f);
@@ -157,12 +158,12 @@ public async Task InlinesAllData(int a, float b, string c, decimal d)
[AutoArguments("\t\r\n")]
[AutoArguments(" ")]
[AutoArguments("")]
- [AutoArguments([null!])]
- public async Task InjectsInlineValues([Frozen] object a,
+ [AutoArguments([null])]
+ public async Task WhenMultipleInlineRows_InjectsInlineValues([Frozen] object a,
[Frozen] PropertyHolder value,
PropertyHolder frozen)
{
await Assert.That(value.Property).IsEqualTo(a);
await Assert.That(value).IsSameReferenceAs(frozen);
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ScenarioTests.cs
new file mode 100644
index 0000000..006fe78
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoArgumentsAttributeTests/ScenarioTests.cs
@@ -0,0 +1,62 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoArgumentsAttributeTests;
+
+public class ScenarioTests
+{
+ [Test]
+ [AutoArguments("foo")]
+ [AutoArguments("foo", "bar")]
+ public async Task WhenInlineValuesProvided_UsesSuppliedValues(string s1, string s2)
+ {
+ await Assert.That(s1).IsEqualTo("foo");
+ await Assert.That(s2).IsNotNull();
+ }
+
+ [Test]
+ [AutoArguments("foo")]
+ [AutoArguments("foo", "bar")]
+ public async Task WhenInlineValuesPartial_SuppliesRemainingSpecimens(string s1, string s2, MyClass myClass)
+ {
+ await Assert.That(s1).IsEqualTo("foo");
+ await Assert.That(s2).IsNotNull();
+ await Assert.That(myClass).IsNotNull();
+ }
+
+ [Test]
+ [AutoArguments("foo")]
+ [AutoArguments("foo", "bar")]
+ public async Task WhenInlineValuesPartial_DoesNotOverwriteSuppliedValues(string s1, string s2, string s3)
+ {
+ await Assert.That(s1).IsEqualTo("foo");
+ await Assert.That(s2).IsNotNull();
+ await Assert.That(s3).IsNotEqualTo("foo");
+ await Assert.That(s3).IsNotEqualTo("bar");
+ }
+
+ [Test]
+ [MyCustomAutoArguments(1337)]
+ [MyCustomAutoArguments(1337, 7)]
+ [MyCustomAutoArguments(1337, 7, 42)]
+ public async Task WhenCustomInlineAttribute_SuppliesExtraValues(int x, int y, int z)
+ {
+ await Assert.That(x).IsEqualTo(1337);
+ await Assert.That(z).IsEqualTo(42);
+ }
+
+ public class MyCustomAutoArgumentsAttribute : AutoArgumentsAttribute
+ {
+ public MyCustomAutoArgumentsAttribute(params object[] values)
+ : base(() => new Fixture().Customize(new TheAnswer()), values)
+ {
+ }
+ }
+
+ private class TheAnswer : ICustomization
+ {
+ public void Customize(IFixture fixture)
+ {
+ fixture.Inject(42);
+ }
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/AutoClassRowCollect.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/AutoClassRowCollect.cs
new file mode 100644
index 0000000..28a560c
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/AutoClassRowCollect.cs
@@ -0,0 +1,16 @@
+using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport;
+using AutoFixture.TUnit.Tests.TestTypes;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests;
+
+internal static class AutoClassRowCollect
+{
+ public static object[][] FromType(Type sourceType, string testMethodName)
+ {
+ var sut = new AutoClassDataSourceAttribute(sourceType);
+ var testMethod = typeof(SampleTestType).GetMethod(testMethodName)!;
+ return sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
+ .Select(x => x())
+ .ToArray();
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs
new file mode 100644
index 0000000..bc217e5
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ClassLevelScenarioTests.cs
@@ -0,0 +1,113 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures;
+using TestTypeFoundation;
+using ConcreteType = TestTypeFoundation.ConcreteType;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests;
+
+///
+/// End-to-end [AutoClassDataSource] on the test class (TUnit ClassParameters).
+/// Ordered simple → complex; mirrors AutoDataSource class-level scenarios.
+///
+[AutoClassDataSource(typeof(StringSequenceClassData))]
+public class ClassLevelPrimitiveScenarioTests(string name, int count)
+{
+ [Test]
+ public async Task WhenAppliedToClass_UsesClassValueAndFillsRemaining()
+ {
+ await Assert.That(["alpha", "beta"]).Contains(name);
+ await Assert.That(count).IsNotEqualTo(0);
+ }
+}
+
+[AutoClassDataSource(typeof(StringSequenceClassData))]
+public class ClassLevelComplexTypeScenarioTests(
+ string name,
+ PropertyHolder ph,
+ SingleParameterType spt,
+ MyClass sut)
+{
+ [Test]
+ public async Task WhenAppliedToClass_UsesClassValueAndFillsComplexRemaining()
+ {
+ await Assert.That(["alpha", "beta"]).Contains(name);
+
+ await Assert.That(ph).IsNotNull();
+ await Assert.That(ph.Property).IsNotNull();
+
+ await Assert.That(spt).IsNotNull();
+ await Assert.That(spt.Parameter).IsNotNull();
+
+ await Assert.That(sut).IsNotNull();
+ await Assert.That(sut.Echo(7)).IsEqualTo(7);
+ }
+}
+
+[AutoClassDataSource(typeof(OneEmptyRowClassData))]
+public class ClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second)
+{
+ [Test]
+ public async Task WhenFrozenOnConstructorParameter_SharesInstanceWithLaterParameter()
+ {
+ await Assert.That(second).IsEqualTo(first);
+ }
+}
+
+[AutoClassDataSource(typeof(OneEmptyRowClassData))]
+public class ClassLevelModestScenarioTests([Modest] MultiUnorderedConstructorType value)
+{
+ [Test]
+ public async Task WhenModestOnConstructorParameter_UsesModestConstructor()
+ {
+ await Assert.That(string.IsNullOrEmpty(value.Text)).IsTrue();
+ await Assert.That(value.Number).IsEqualTo(0);
+ }
+}
+
+[AutoClassDataSource(typeof(StringSequenceClassData))]
+public class ClassLevelMultiConstructorParameterizedFirstScenarioTests
+{
+ private readonly string name;
+
+ public ClassLevelMultiConstructorParameterizedFirstScenarioTests(string name)
+ {
+ this.name = name;
+ }
+
+ public ClassLevelMultiConstructorParameterizedFirstScenarioTests()
+ {
+ this.name = "parameterless";
+ }
+
+ [Test]
+ public async Task WhenParameterizedConstructorDeclaredFirst_UsesClassConstructorArgument()
+ {
+ await Assert.That(["alpha", "beta"]).Contains(this.name);
+ }
+}
+
+[AutoClassDataSource(typeof(IntSequenceClassData))]
+public class ClassLevelMultiConstructorIntFirstScenarioTests
+{
+ private readonly string name;
+ private readonly int count;
+
+ public ClassLevelMultiConstructorIntFirstScenarioTests(int count)
+ {
+ this.name = "int-ctor";
+ this.count = count;
+ }
+
+ public ClassLevelMultiConstructorIntFirstScenarioTests(string name)
+ {
+ this.name = name;
+ this.count = -1;
+ }
+
+ [Test]
+ public async Task WhenIntConstructorDeclaredFirst_UsesClassIntArgument()
+ {
+ await Assert.That(this.name).IsEqualTo("int-ctor");
+ await Assert.That([11, 22]).Contains(this.count);
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/EmptySequenceRowTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/EmptySequenceRowTests.cs
new file mode 100644
index 0000000..b49eefc
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/EmptySequenceRowTests.cs
@@ -0,0 +1,21 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests;
+
+///
+/// Empty class sequences cannot be asserted via a [Test] body (no cases run),
+/// so they stay as direct GetData checks.
+///
+public class EmptySequenceRowTests
+{
+ [Test]
+ public async Task GetData_WhenClassYieldsEmptyAsyncSequence_YieldsNoRows()
+ {
+ var result = AutoClassRowCollect.FromType(
+ typeof(EmptyAsyncObjectArrayClassData),
+ nameof(SampleTestType.TestMethodWithTwoParameters));
+
+ await Assert.That(result).IsEmpty();
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs
new file mode 100644
index 0000000..d499cbb
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericClassLevelScenarioTests.cs
@@ -0,0 +1,53 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures;
+using TestTypeFoundation;
+using ConcreteType = TestTypeFoundation.ConcreteType;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests;
+
+///
+/// Class-level [AutoClassDataSource<T>] scenarios parallel to the non-generic class-level set.
+///
+[AutoClassDataSource]
+public class GenericClassLevelPrimitiveScenarioTests(string name, int count)
+{
+ [Test]
+ public async Task WhenGenericAppliedToClass_UsesClassValueAndFillsRemaining()
+ {
+ await Assert.That(["alpha", "beta"]).Contains(name);
+ await Assert.That(count).IsNotEqualTo(0);
+ }
+}
+
+[AutoClassDataSource]
+public class GenericClassLevelComplexTypeScenarioTests(
+ string name,
+ PropertyHolder ph,
+ SingleParameterType spt,
+ MyClass sut)
+{
+ [Test]
+ public async Task WhenGenericAppliedToClass_UsesClassValueAndFillsComplexRemaining()
+ {
+ await Assert.That(["alpha", "beta"]).Contains(name);
+
+ await Assert.That(ph).IsNotNull();
+ await Assert.That(ph.Property).IsNotNull();
+
+ await Assert.That(spt).IsNotNull();
+ await Assert.That(spt.Parameter).IsNotNull();
+
+ await Assert.That(sut).IsNotNull();
+ await Assert.That(sut.Echo(7)).IsEqualTo(7);
+ }
+}
+
+[AutoClassDataSource]
+public class GenericClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second)
+{
+ [Test]
+ public async Task WhenGenericFrozenOnConstructorParameter_SharesInstanceWithLaterParameter()
+ {
+ await Assert.That(second).IsEqualTo(first);
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs
new file mode 100644
index 0000000..16925a0
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GenericUsageScenarioTests.cs
@@ -0,0 +1,108 @@
+using System.Collections;
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests;
+
+///
+/// End-to-end [AutoClassDataSource<T>] usage parallel to the non-generic scenarios.
+///
+public class GenericUsageScenarioTests
+{
+ [Test, AutoClassDataSource]
+ public async Task WhenGenericClassSuppliesValues_UsesSuppliedValues(string s1, string s2, string s3)
+ {
+ await Assert.That(["foo", "dim"]).Contains(s1);
+ await Assert.That(s2).IsNotEmpty();
+ await Assert.That(s3).IsNotEmpty();
+ }
+
+ [Test, AutoClassDataSource]
+ public async Task WhenGenericClassValuesPartial_SuppliesRemainingSpecimens(
+ string s1, string s2, string s3, MyClass myClass)
+ {
+ await Assert.That(s1).IsNotEmpty();
+ await Assert.That(s2).IsNotEmpty();
+ await Assert.That(s3).IsNotEmpty();
+ await Assert.That(myClass).IsNotNull();
+ }
+
+ [Test, AutoClassDataSource(28, "bar", 93.102)]
+ public async Task WhenGenericClassDataParameterized_ReceivesExpectedData(
+ int p1, string p2, double p3, RecordType p4)
+ {
+ object[] actual = [p1, p2, p3];
+ object[] expected = [28, "bar", 93.102];
+
+ await Assert.That(actual).IsEquivalentTo(expected);
+ await Assert.That(p4).IsNotNull();
+ }
+
+ [Test, MyCustomAutoClassDataSource]
+ public async Task WhenGenericCustomClassAttribute_SuppliesExtraValues(int x, int y, int z)
+ {
+ await Assert.That(x).IsEqualTo(1337);
+ await Assert.That(y).IsNotEqualTo(0);
+ await Assert.That(z).IsEqualTo(42);
+ }
+
+ public class StringDataClass : IEnumerable
+ {
+ public IEnumerator GetEnumerator()
+ {
+ yield return ["foo", "bar", "foobar"];
+ yield return ["dim", "sum", "dimsum"];
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
+ }
+
+ public class ParameterizedDataClass : IEnumerable
+ {
+ private readonly int p1;
+ private readonly string p2;
+ private readonly double p3;
+
+ public ParameterizedDataClass(int p1, string p2, double p3)
+ {
+ this.p1 = p1;
+ this.p2 = p2;
+ this.p3 = p3;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ yield return [this.p1, this.p2, this.p3];
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
+ }
+
+ public class IntDataClass : IEnumerable
+ {
+ public IEnumerator GetEnumerator()
+ {
+ yield return [1337];
+ yield return [1337, 7];
+ yield return [1337, 7, 42];
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
+ }
+
+ public class MyCustomAutoClassDataSourceAttribute : AutoClassDataSourceAttribute
+ {
+ public MyCustomAutoClassDataSourceAttribute(params object[] parameters)
+ : base(() => new Fixture().Customize(new TheAnswer()), parameters)
+ {
+ }
+ }
+
+ private class TheAnswer : ICustomization
+ {
+ public void Customize(IFixture fixture)
+ {
+ fixture.Inject(42);
+ }
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceAttributeTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs
similarity index 73%
rename from tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceAttributeTests.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs
index 9018b1a..b75fb2e 100644
--- a/tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceAttributeTests.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/GetDataTests.cs
@@ -1,23 +1,23 @@
-using System.Collections;
+using System.Collections;
using AutoFixture.Kernel;
+using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport;
using AutoFixture.TUnit.Tests.TestTypes;
using TestTypeFoundation;
-using TUnit.Assertions.Extensions;
using ConcreteType = TestTypeFoundation.ConcreteType;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests;
public class ClassAutoDataSourceAttributeTests
{
[Test]
- public void CanCreateInstance()
+ public void Constructor_WhenCreated_CanCreateInstance()
{
// Act & Assert
_ = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData));
}
[Test]
- public async Task IsDataAttribute()
+ public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute()
{
// Arrange & Act
var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData));
@@ -27,17 +27,17 @@ public async Task IsDataAttribute()
}
[Test]
- public async Task ThrowsWhenSourceTypeIsNull()
+ public async Task Constructor_WhenSourceTypeIsNull_Throws()
{
// Act & Assert
- await Assert.That(() => new AutoClassDataSourceAttribute(null!)).ThrowsExactly();
+ await Assert.That(() => new AutoClassDataSourceAttribute(null)).ThrowsExactly();
}
[Test]
- public async Task TreatsNullParameterValueAsArrayWithNull()
+ public async Task Constructor_WhenParameterValueIsNull_TreatsAsArrayWithNull()
{
// Arrange & Act
- var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData), null!);
+ var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData), null);
// Assert
await Assert.That(sut.Parameters).HasSingleItem()
@@ -46,47 +46,52 @@ await Assert.That(sut.Parameters).HasSingleItem()
}
[Test]
- public async Task ThrowsWhenFixtureFactoryIsNull()
+ public async Task Constructor_WhenFixtureFactoryIsNull_Throws()
{
// Act & Assert
await Assert.That(() => new DerivedAutoClassDataSourceAttribute(
- fixtureFactory: null!, typeof(MixedTypeClassData))).ThrowsExactly();
+ fixtureFactory: null, typeof(MixedTypeClassData))).ThrowsExactly();
}
[Test]
- public async Task GetDataThrowsWhenSourceTypeNotEnumerable()
+ public async Task GetData_WhenSourceTypeIsScalar_ReturnsSingleRow()
{
// Arrange
var sut = new AutoClassDataSourceAttribute(typeof(MyClass));
var testMethod = typeof(ExampleTestClass)
.GetMethod(nameof(ExampleTestClass.TestMethod));
- // Act & Assert
- await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!))
- .Select(x => x()).ToArray()).ThrowsExactly();
+ // Act
+ var data = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
+ .Select(x => x()).ToArray();
+
+ // Assert — scalar class instance is one supplied argument; remaining are auto-generated
+ await Assert.That(data.Length).IsEqualTo(1);
+ await Assert.That(data[0].Length).IsEqualTo(testMethod.GetParameters().Length);
+ await Assert.That(data[0][0]).IsAssignableTo();
}
[Test]
- public async Task GetDataThrowsWhenParametersDoNotMatchConstructor()
+ public async Task GetData_WhenParametersDoNotMatchConstructor_Throws()
{
// Arrange
- var sut = new AutoClassDataSourceAttribute(typeof(MyClass), "myString", 33, null!);
+ var sut = new AutoClassDataSourceAttribute(typeof(MyClass), "myString", 33, null);
var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod));
// Act & Assert
- await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!))
+ await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
.Select(x => x()).ToArray()).ThrowsException();
}
[Test]
- public async Task GetDataDoesNotThrowWhenSourceYieldsNoResults()
+ public async Task GetData_WhenSourceYieldsNoResults_DoesNotThrow()
{
// Arrange
var sut = new AutoClassDataSourceAttribute(typeof(EmptyClassData));
var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod));
// Act
- var data = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!))
+ var data = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
;
// Assert
@@ -94,91 +99,91 @@ public async Task GetDataDoesNotThrowWhenSourceYieldsNoResults()
}
[Test]
- public async Task GetDataThrowsWhenSourceYieldsNullResults()
+ public async Task GetData_WhenSourceYieldsNullResults_Throws()
{
// Arrange
var sut = new AutoClassDataSourceAttribute(typeof(ClassWithNullTestData));
var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod));
// Act & assert
- await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!))
+ await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
.Select(x => x()).ToArray()).ThrowsException();
}
[Test]
- public void GetDataDoesNotThrow()
+ public void GetData_WhenCalled_DoesNotThrow()
{
// Arrange
var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData));
var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod));
// Act & Assert
- sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!));
+ sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod));
}
[Test]
- public async Task GetDataReturnsEnumerable()
+ public async Task GetData_WhenCalled_ReturnsEnumerable()
{
// Arrange
var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData));
var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod));
// Act
- var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!));
+ var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod));
// Assert
await Assert.That(actual).IsNotNull();
}
[Test]
- public async Task GetDataReturnsNonEmptyEnumerable()
+ public async Task GetData_WhenCalled_ReturnsNonEmptyEnumerable()
{
// Arrange
var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData));
var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod));
// Act
- var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!));
+ var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod));
// Assert
await Assert.That(actual).IsNotEmpty();
}
[Test]
- public async Task GetDataReturnsExpectedTestDataCount()
+ public async Task GetData_WhenCalled_ReturnsExpectedRowCount()
{
// Arrange
var sut = new AutoClassDataSourceAttribute(typeof(MixedTypeClassData));
var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod));
// Act
- var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!));
+ var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod));
// Assert
- await Assert.That(actual).HasCount().EqualTo(5);
+ await Assert.That(actual).Count().IsEqualTo(5);
}
[Test]
- public async Task GetDataThrowsWhenDataSourceNotEnumerable()
+ public async Task GetData_WhenDataSourceNotEnumerable_Throws()
{
// Arrange
var sut = new AutoClassDataSourceAttribute(typeof(GuardedConstructorHost));
var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod));
// Act & Assert
- await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!))
+ await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
.Select(x => x()).ToArray()).ThrowsException();
}
[Test]
- public async Task GetDataThrowsForNonMatchingConstructorTypes()
+ public async Task GetData_WhenConstructorTypesDoNotMatch_Throws()
{
// Arrange
- var sut = new AutoClassDataSourceAttribute(typeof(DelegatingTestData), "myString", 33, null!);
+ var sut = new AutoClassDataSourceAttribute(typeof(DelegatingTestData), "myString", 33, null);
var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod));
// Act & Assert
- await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!))
+ await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
.Select(x => x()).ToArray()).ThrowsException();
}
@@ -195,7 +200,7 @@ await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.Crea
[Arguments("CreateWithModestAndFrozen")]
[Arguments("CreateWithFrozenAndNoAutoProperties")]
[Arguments("CreateWithNoAutoPropertiesAndFrozen")]
- public async Task GetDataOrdersCustomizationAttributes(string methodName)
+ public async Task GetData_WhenCustomizationsPresent_OrdersThem(string methodName)
{
// Arrange
var method = typeof(TypeWithCustomizationAttributes)
@@ -209,7 +214,7 @@ public async Task GetDataOrdersCustomizationAttributes(string methodName)
var sut = new DerivedAutoClassDataSourceAttribute(() => fixture, typeof(ClassWithEmptyTestData));
// Act
- _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!))
+ _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method))
.Select(x => x())
.ToArray();
@@ -223,7 +228,7 @@ public async Task GetDataOrdersCustomizationAttributes(string methodName)
}
[Test]
- public async Task GetDataReturnsExpectedTestData()
+ public async Task GetData_WhenCalled_ReturnsExpectedTestData()
{
var builder = new CompositeSpecimenBuilder(
new FixedParameterBuilder("a", 1),
@@ -243,7 +248,7 @@ public async Task GetDataReturnsExpectedTestData()
[-95, "test-92", EnumType.Second, new Tuple("myValue", 5)]
];
- var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!))
+ var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
.Select(x => x())
.ToArray();
@@ -251,7 +256,7 @@ public async Task GetDataReturnsExpectedTestData()
}
[Test]
- public async Task GetDataReturnsExpectedTestDataFromParameterizedSource()
+ public async Task GetData_WhenParameterizedSource_ReturnsExpectedTestData()
{
var builder = new CompositeSpecimenBuilder(
new FixedParameterBuilder("a", 1),
@@ -268,7 +273,7 @@ public async Task GetDataReturnsExpectedTestDataFromParameterizedSource()
[29, "myValue", EnumType.Third, new Tuple("value", 1)]
];
- var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!))
+ var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
.Select(x => x())
.ToArray();
@@ -276,21 +281,20 @@ public async Task GetDataReturnsExpectedTestDataFromParameterizedSource()
}
[Test]
- public async Task TestWithNullParametersPasses()
+ public async Task WhenNullParameters_Passes()
{
// Arrange
var sut = new AutoClassDataSourceAttribute(typeof(TestDataWithNullValues));
var testMethod = typeof(ExampleTestClass>)
.GetMethod(nameof(ExampleTestClass>.TestMethod));
- var expected = new[]
- {
- new object[] { null!, null!, null!, null! },
- new object[] { string.Empty, null!, null!, null! },
- new object[] { null!, " ", null!, null! },
- };
+ object[][] expected = [
+ [ null, null, null, null ],
+ [string.Empty, null, null, null],
+ [null, " ", null, null],
+ ];
// Act
- var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!))
+ var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
.Select(x => x())
.ToArray();
@@ -302,9 +306,9 @@ public class TestDataWithNullValues : IEnumerable
{
public IEnumerator GetEnumerator()
{
- yield return [null!, null!, null!, null!];
- yield return [string.Empty, null!, null!, null!];
- yield return [null!, " ", null!, null!];
+ yield return [null, null, null, null];
+ yield return [string.Empty, null, null, null];
+ yield return [null, " ", null, null];
}
IEnumerator IEnumerable.GetEnumerator()
@@ -312,4 +316,4 @@ IEnumerator IEnumerable.GetEnumerator()
return this.GetEnumerator();
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/NullRowTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/NullRowTests.cs
new file mode 100644
index 0000000..56f822e
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/NullRowTests.cs
@@ -0,0 +1,21 @@
+using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport;
+using AutoFixture.TUnit.Tests.TestTypes;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests;
+
+public class NullRowTests
+{
+ [Test]
+ public async Task GetData_WhenClassYieldsNullRows_ThrowsInvalidOperationException()
+ {
+ var sut = new AutoClassDataSourceAttribute(typeof(ClassWithNullTestData));
+ var testMethod = typeof(ExampleTestClass).GetMethod(nameof(ExampleTestClass.TestMethod));
+ var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod);
+
+ var act = () => sut.GenerateDataSources(metadata)
+ .Select(row => row())
+ .ToArray();
+
+ await Assert.That(act).ThrowsExactly();
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs
new file mode 100644
index 0000000..7a38c60
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ResultShapeScenarioTests.cs
@@ -0,0 +1,77 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures;
+using TestTypeFoundation;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests;
+
+///
+/// End-to-end [AutoClassDataSource] coverage for README result shapes.
+///
+public class ResultShapeScenarioTests
+{
+ [Test]
+ [AutoClassDataSource(typeof(StringSequenceClassData))]
+ public async Task WhenClassYieldsStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover)
+ {
+ await Assert.That(["alpha", "beta"]).Contains(value);
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoClassDataSource(typeof(TupleSequenceClassData))]
+ public async Task WhenClassYieldsTuples_ExpandsColumnsAndFillsRemaining(
+ string left, int right, MyClass leftover)
+ {
+ await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right));
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoClassDataSource(typeof(ObjectArrayClassData))]
+ public async Task WhenClassYieldsObjectArrays_UsesSuppliedValues(
+ string a, int b, RecordType c)
+ {
+ await Assert.That<(string, int, string)[]>([
+ ("hello", 1, "world"),
+ ("foo", 2, "bar")
+ ]).Contains((a, b, c.Value));
+ }
+
+ [Test]
+ [AutoClassDataSource(typeof(AsyncObjectArrayClassData))]
+ public async Task WhenClassYieldsAsyncObjectArrays_UsesSuppliedValues(
+ string a, int b, RecordType c)
+ {
+ await Assert.That<(string, int, string)[]>([
+ ("hello", 1, "world"),
+ ("foo", 2, "bar")
+ ]).Contains((a, b, c.Value));
+ }
+
+ [Test]
+ [AutoClassDataSource(typeof(AsyncStringSequenceClassData))]
+ public async Task WhenClassYieldsAsyncStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover)
+ {
+ await Assert.That(["alpha", "beta"]).Contains(value);
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoClassDataSource(typeof(AsyncTupleSequenceClassData))]
+ public async Task WhenClassYieldsAsyncTuples_ExpandsColumnsAndFillsRemaining(
+ string left, int right, MyClass leftover)
+ {
+ await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right));
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoClassDataSource(typeof(StringScalarClassData))]
+ public async Task WhenClassIsScalar_UsesInstanceAsCellAndFillsRemaining(
+ StringScalarClassData seed, MyClass leftover)
+ {
+ await Assert.That(seed).IsNotNull();
+ await Assert.That(seed.Value).IsEqualTo("seed");
+ await Assert.That(leftover).IsNotNull();
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ScenarioTests.cs
similarity index 84%
rename from tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceScenarioTests.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ScenarioTests.cs
index 6489839..1218dad 100644
--- a/tests/AutoFixture.TUnit.Tests/ClassAutoDataSourceScenarioTests.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/ScenarioTests.cs
@@ -1,13 +1,13 @@
-using AutoFixture.TUnit.Tests.TestTypes;
+using AutoFixture.TUnit.Tests.TestTypes;
using TestTypeFoundation;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests;
public class ClassAutoDataSourceScenarioTests
{
[Test]
[AutoClassDataSource(typeof(MixedTypeClassData))]
- public async Task TestWithMixedTypesPasses(int? a, string b, EnumType? c, Tuple d)
+ public async Task WhenMixedTypes_Passes(int? a, string b, EnumType? c, Tuple d)
{
await Assert.That(a).IsNotNull();
await Assert.That(b).IsNotNull();
@@ -17,7 +17,7 @@ public async Task TestWithMixedTypesPasses(int? a, string b, EnumType? c, Tuple<
[Test]
[AutoClassDataSource(typeof(ParameterizedClassData), 42, "test-13", EnumType.Third)]
- public async Task TestWithParameterizedClassDataReceivesExpectedData(
+ public async Task WhenParameterizedClassData_ReceivesExpectedData(
int a, string b, EnumType c, PropertyHolder d)
{
await Assert.That(a).IsEqualTo(42);
@@ -28,7 +28,7 @@ public async Task TestWithParameterizedClassDataReceivesExpectedData(
[Test]
[AutoClassDataSource(typeof(ParameterizedClassData), 13, "test-46", EnumType.Second)]
- public async Task TestWithFrozenParametersReceivesExpectedData(
+ public async Task WhenFrozenParameters_ReceivesExpectedData(
[Frozen] int a, [Frozen] string b, [Frozen] EnumType c,
PropertyHolder a1, PropertyHolder b1, PropertyHolder c1)
{
@@ -43,7 +43,7 @@ public async Task TestWithFrozenParametersReceivesExpectedData(
[Test]
[AutoClassDataSource(typeof(ParameterizedClassData), 59, "hello-world", EnumType.Second)]
- public async Task TestWithInjectedValuesRespectsOtherParameterCustomizations(
+ public async Task WhenInjectedValues_RespectsOtherParameterCustomizations(
[Frozen] int a, [Frozen] string b, [Frozen] EnumType c,
[FavorEnumerables] CompositeTypeWithOverloadedConstructors numbers,
[FavorArrays] CompositeTypeWithOverloadedConstructors strings,
@@ -60,4 +60,4 @@ public async Task TestWithInjectedValuesRespectsOtherParameterCustomizations(
await Assert.That(enums.Items).IsAssignableTo>();
await Assert.That(enums.Items).All().Satisfy(item => item.IsEqualTo(c));
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs
new file mode 100644
index 0000000..eb44231
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoClassDataSourceAttributeTests/UsageScenarioTests.cs
@@ -0,0 +1,128 @@
+using System.Collections;
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoClassDataSourceAttributeTests;
+
+///
+/// End-to-end [AutoClassDataSource] usage moved from the old Scenarios bucket.
+///
+public class UsageScenarioTests
+{
+ [Test, AutoClassDataSource(typeof(StringDataClass))]
+ public async Task WhenClassSuppliesValues_UsesSuppliedValues(string s1, string s2, string s3)
+ {
+ await Assert.That(["foo", "dim"]).Contains(s1);
+ await Assert.That(s2).IsNotEmpty();
+ await Assert.That(s3).IsNotEmpty();
+ }
+
+ [Test, AutoClassDataSource(typeof(StringDataClass))]
+ public async Task WhenClassValuesPartial_SuppliesRemainingSpecimens(string s1, string s2, string s3, MyClass myClass)
+ {
+ await Assert.That(s1).IsNotEmpty();
+ await Assert.That(s2).IsNotEmpty();
+ await Assert.That(s3).IsNotEmpty();
+ await Assert.That(myClass).IsNotNull();
+ }
+
+ [Test, AutoClassDataSource(typeof(MixedDataClass))]
+ public async Task WhenMixedTypes_SuppliesExpectedData(int p1, string p2, PropertyHolder p3, MyClass myClass)
+ {
+ await Assert.That(p1).IsNotEqualTo(0);
+ await Assert.That(p2).IsNotEmpty();
+ await Assert.That(p3).IsNotNull();
+ await Assert.That(p3.Property).IsNotEmpty();
+ await Assert.That(myClass).IsNotNull();
+ }
+
+ [Test, AutoClassDataSource(typeof(ParameterizedDataClass), 28, "bar", 93.102)]
+ public async Task WhenClassDataParameterized_ReceivesExpectedData(int p1, string p2, double p3, RecordType p4)
+ {
+ object[] actual = [p1, p2, p3];
+ object[] expected = [28, "bar", 93.102];
+
+ await Assert.That(actual).IsEquivalentTo(expected);
+ await Assert.That(p4).IsNotNull();
+ }
+
+ [Test, MyCustomAutoClassDataSource(typeof(IntDataClass))]
+ public async Task WhenCustomClassAttribute_SuppliesExtraValues(int x, int y, int z)
+ {
+ await Assert.That(x).IsEqualTo(1337);
+ await Assert.That(y).IsNotEqualTo(0);
+ await Assert.That(z).IsEqualTo(42);
+ }
+
+ public class StringDataClass : IEnumerable
+ {
+ public IEnumerator GetEnumerator()
+ {
+ yield return ["foo", "bar", "foobar"];
+ yield return ["dim", "sum", "dimsum"];
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
+ }
+
+ public class MixedDataClass : IEnumerable
+ {
+ public IEnumerator GetEnumerator()
+ {
+ yield return [1];
+ yield return [4, "testValue"];
+ yield return [20, "otherValue", new PropertyHolder { Property = "testValue1" }];
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
+ }
+
+ public class ParameterizedDataClass : IEnumerable
+ {
+ private readonly int p1;
+ private readonly string p2;
+ private readonly double p3;
+
+ public ParameterizedDataClass(int p1, string p2, double p3)
+ {
+ this.p1 = p1;
+ this.p2 = p2;
+ this.p3 = p3;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ yield return [this.p1, this.p2, this.p3];
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
+ }
+
+ public class IntDataClass : IEnumerable
+ {
+ public IEnumerator GetEnumerator()
+ {
+ yield return [1337];
+ yield return [1337, 7];
+ yield return [1337, 7, 42];
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
+ }
+
+ public class MyCustomAutoClassDataSourceAttribute : AutoClassDataSourceAttribute
+ {
+ public MyCustomAutoClassDataSourceAttribute(Type sourceType, params object[] parameters)
+ : base(() => new Fixture().Customize(new TheAnswer()), sourceType, parameters)
+ {
+ }
+ }
+
+ private class TheAnswer : ICustomization
+ {
+ public void Customize(IFixture fixture)
+ {
+ fixture.Inject(42);
+ }
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ClassLevelScenarioTests.cs
new file mode 100644
index 0000000..8dd18a7
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ClassLevelScenarioTests.cs
@@ -0,0 +1,119 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+using ConcreteType = TestTypeFoundation.ConcreteType;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoDataSourceAttributeTests;
+
+///
+/// End-to-end [AutoDataSource] on the test class (TUnit ClassParameters).
+/// Ordered simple → complex.
+///
+[AutoDataSource]
+public class ClassLevelPrimitiveScenarioTests(string name, int count)
+{
+ [Test]
+ public async Task WhenAppliedToClass_FillsPrimitiveConstructorParameters()
+ {
+ await Assert.That(name).IsNotEmpty();
+ await Assert.That(count).IsNotEqualTo(0);
+ }
+}
+
+[AutoDataSource]
+public class ClassLevelComplexTypeScenarioTests(
+ PropertyHolder ph,
+ SingleParameterType spt,
+ MyClass sut)
+{
+ [Test]
+ public async Task WhenAppliedToClass_FillsComplexConstructorParameters()
+ {
+ await Assert.That(ph).IsNotNull();
+ await Assert.That(ph.Property).IsNotNull();
+
+ await Assert.That(spt).IsNotNull();
+ await Assert.That(spt.Parameter).IsNotNull();
+
+ await Assert.That(sut).IsNotNull();
+ await Assert.That(sut.Echo(7)).IsEqualTo(7);
+ }
+}
+
+[AutoDataSource]
+public class ClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second)
+{
+ [Test]
+ public async Task WhenFrozenOnConstructorParameter_SharesInstanceWithLaterParameter()
+ {
+ await Assert.That(second).IsEqualTo(first);
+ }
+}
+
+[AutoDataSource]
+public class ClassLevelModestScenarioTests([Modest] MultiUnorderedConstructorType value)
+{
+ [Test]
+ public async Task WhenModestOnConstructorParameter_UsesModestConstructor()
+ {
+ await Assert.That(string.IsNullOrEmpty(value.Text)).IsTrue();
+ await Assert.That(value.Number).IsEqualTo(0);
+ }
+}
+
+///
+/// Parameterized constructor is declared first so TUnit Class.Parameters describe it.
+/// A parameterless overload exists so GetConstructors().First() is not a reliable match.
+///
+[AutoDataSource]
+public class ClassLevelMultiConstructorParameterizedFirstScenarioTests
+{
+ private readonly string name;
+
+ public ClassLevelMultiConstructorParameterizedFirstScenarioTests(string name)
+ {
+ this.name = name;
+ }
+
+ public ClassLevelMultiConstructorParameterizedFirstScenarioTests()
+ {
+ this.name = "parameterless";
+ }
+
+ [Test]
+ public async Task WhenParameterizedConstructorDeclaredFirst_FillsMatchingConstructor()
+ {
+ await Assert.That(this.name).IsNotEqualTo("parameterless");
+ await Assert.That(this.name).IsNotEmpty();
+ }
+}
+
+///
+/// Two parameterized constructors: int overload is declared first, so TUnit Class.Parameters
+/// describe that constructor and AutoDataSource fills it.
+///
+[AutoDataSource]
+public class ClassLevelMultiConstructorIntFirstScenarioTests
+{
+ private readonly string name;
+ private readonly int count;
+
+ public ClassLevelMultiConstructorIntFirstScenarioTests(int count)
+ {
+ this.name = "int-ctor";
+ this.count = count;
+ }
+
+ public ClassLevelMultiConstructorIntFirstScenarioTests(string name)
+ {
+ this.name = name;
+ this.count = -1;
+ }
+
+ [Test]
+ public async Task WhenIntConstructorDeclaredFirst_FillsIntConstructor()
+ {
+ await Assert.That(this.name).IsEqualTo("int-ctor");
+ await Assert.That(this.count).IsNotEqualTo(0);
+ await Assert.That(this.count).IsNotEqualTo(-1);
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/AutoDataSourceAttributeTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/GetDataTests.cs
similarity index 77%
rename from tests/AutoFixture.TUnit.Tests/AutoDataSourceAttributeTests.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/GetDataTests.cs
index a7da5ec..f4fa060 100644
--- a/tests/AutoFixture.TUnit.Tests/AutoDataSourceAttributeTests.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/GetDataTests.cs
@@ -1,15 +1,15 @@
-using AutoFixture.Kernel;
+using AutoFixture.Kernel;
+using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport;
using AutoFixture.TUnit.Tests.TestTypes;
using TestTypeFoundation;
-using TUnit.Assertions.Extensions;
using ConcreteType = TestTypeFoundation.ConcreteType;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.AutoDataSourceAttributeTests;
public class AutoDataSourceAttributeTests
{
[Test]
- public async Task SutIsDataAttribute()
+ public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute()
{
// Arrange & Act
var sut = new AutoDataSourceAttribute();
@@ -19,7 +19,7 @@ public async Task SutIsDataAttribute()
}
[Test]
- public async Task InitializedWithDefaultConstructorHasCorrectFixture()
+ public async Task Constructor_WhenDefault_HasCorrectFixture()
{
// Arrange
var sut = new AutoDataSourceAttribute();
@@ -32,7 +32,7 @@ public async Task InitializedWithDefaultConstructorHasCorrectFixture()
}
[Test]
- public async Task InitializedWithFixtureFactoryConstructorHasCorrectFixture()
+ public async Task Constructor_WhenFixtureFactoryProvided_HasCorrectFixture()
{
// Arrange
var fixture = new Fixture();
@@ -45,16 +45,16 @@ public async Task InitializedWithFixtureFactoryConstructorHasCorrectFixture()
}
[Test]
- public async Task InitializeWithNullFixtureFactoryThrows()
+ public async Task Constructor_WhenFixtureFactoryIsNull_Throws()
{
// Arrange
// Act & Assert
await Assert.That(() =>
- new DerivedAutoDataSourceAttribute(null!)).ThrowsExactly();
+ new DerivedAutoDataSourceAttribute(null)).ThrowsExactly();
}
[Test]
- public async Task DoesntActivateFixtureImmediately()
+ public async Task Constructor_WhenCreated_DoesNotActivateFixtureImmediately()
{
// Arrange
var wasInvoked = false;
@@ -63,7 +63,7 @@ public async Task DoesntActivateFixtureImmediately()
_ = new DerivedAutoDataSourceAttribute(() =>
{
wasInvoked = true;
- return null!;
+ return null;
});
// Assert
@@ -71,26 +71,26 @@ public async Task DoesntActivateFixtureImmediately()
}
[Test]
- public async Task GetDataWithNullMethodThrows()
+ public async Task GetData_WhenMethodIsNull_Throws()
{
// Arrange
var sut = new AutoDataSourceAttribute();
// Act & assert
- await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(null!, null!))).ThrowsException();
+ await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(null, null))).ThrowsException();
}
[Test]
- public async Task GetDataReturnsCorrectResult()
+ public async Task GetData_WhenCalled_ReturnsCorrectResult()
{
// Arrange
var method = typeof(TypeWithOverloadedMembers)
.GetMethod("DoSomething", [typeof(object)]);
- var parameters = method!.GetParameters();
+ var parameters = method.GetParameters();
var expectedResult = new object();
- object actualParameter = null!;
- ISpecimenContext actualContext = null!;
+ object actualParameter = null;
+ ISpecimenContext actualContext = null;
var builder = new DelegatingSpecimenBuilder
{
OnCreate = (r, c) =>
@@ -111,8 +111,8 @@ public async Task GetDataReturnsCorrectResult()
// Assert
await Assert.That(actualContext).IsNotNull();
await Assert.That(parameters).HasSingleItem();
- await Assert.That(actualParameter).IsEqualTo(parameters[0]);
- await Assert.That(result.Single()).IsEquivalentTo(new[] { expectedResult });
+ await Assert.That(actualParameter).IsSameReferenceAs(parameters[0]);
+ await Assert.That(result.Single()).IsEquivalentTo([expectedResult]);
}
[Test]
@@ -128,7 +128,7 @@ public async Task GetDataReturnsCorrectResult()
[Arguments("CreateWithModestAndFrozen")]
[Arguments("CreateWithFrozenAndNoAutoProperties")]
[Arguments("CreateWithNoAutoPropertiesAndFrozen")]
- public async Task GetDataOrdersCustomizationAttributes(string methodName)
+ public async Task GetData_WhenCustomizationsPresent_OrdersThem(string methodName)
{
// Arrange
var method = typeof(TypeWithCustomizationAttributes)
@@ -155,7 +155,7 @@ public async Task GetDataOrdersCustomizationAttributes(string methodName)
}
[Test]
- public async Task ShouldRecognizeAttributesImplementingIParameterCustomizationSource()
+ public async Task GetData_WhenParameterImplementsIParameterCustomizationSource_AppliesCustomization()
{
// Arrange
var method = typeof(TypeWithIParameterCustomizationSourceUsage)
@@ -176,4 +176,4 @@ public async Task ShouldRecognizeAttributesImplementingIParameterCustomizationSo
// Assert
await Assert.That(customizationLog[0]).IsAssignableTo();
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ScenarioTests.cs
new file mode 100644
index 0000000..47f7a1d
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoDataSourceAttributeTests/ScenarioTests.cs
@@ -0,0 +1,45 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+using ConcreteType = TestTypeFoundation.ConcreteType;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoDataSourceAttributeTests;
+
+public class ScenarioTests
+{
+ [Test, AutoDataSource]
+ public async Task WhenIntegerParameter_ProvidesNonDefaultValue(int primitiveValue)
+ {
+ await Assert.That(primitiveValue).IsNotEqualTo(0);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenStringParameter_ProvidesNonDefaultValue(string text)
+ {
+ await Assert.That(text).StartsWith("text");
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenObjectParameter_ProvidesNonNullInstance(PropertyHolder ph)
+ {
+ await Assert.That(ph).IsNotNull();
+ await Assert.That(ph.Property).IsNotNull();
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenMultipleParameters_ProvidesNonNullInstances(PropertyHolder ph, SingleParameterType spt)
+ {
+ await Assert.That(ph).IsNotNull();
+ await Assert.That(ph.Property).IsNotNull();
+
+ await Assert.That(spt).IsNotNull();
+ await Assert.That(spt.Parameter).IsNotNull();
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenExpectedNumberAndSut_AssignsExpectedNumberToSut(int expectedNumber, MyClass sut)
+ {
+ int result = sut.Echo(expectedNumber);
+
+ await Assert.That(result).IsEqualTo(expectedNumber);
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/AutoMemberRowCollect.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/AutoMemberRowCollect.cs
new file mode 100644
index 0000000..7eacd23
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/AutoMemberRowCollect.cs
@@ -0,0 +1,17 @@
+using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport;
+using AutoFixture.TUnit.Tests.TestTypes;
+using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests;
+
+internal static class AutoMemberRowCollect
+{
+ public static object[][] FromMember(string memberName, string testMethodName)
+ {
+ var sut = new AutoMemberDataSourceAttribute(typeof(MemberDataShapes), memberName);
+ var testMethod = typeof(SampleTestType).GetMethod(testMethodName)!;
+ return sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod))
+ .Select(x => x())
+ .ToArray();
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs
new file mode 100644
index 0000000..eaea433
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ClassLevelScenarioTests.cs
@@ -0,0 +1,130 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+using ConcreteType = TestTypeFoundation.ConcreteType;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests;
+
+///
+/// End-to-end [AutoMemberDataSource] on the test class (TUnit ClassParameters).
+/// Ordered simple → complex; mirrors AutoDataSource class-level scenarios.
+///
+[AutoMemberDataSource(nameof(Names))]
+public class ClassLevelPrimitiveScenarioTests(string name, int count)
+{
+ public static IEnumerable Names => ["one", "two"];
+
+ [Test]
+ public async Task WhenAppliedToClass_UsesMemberValueAndFillsRemaining()
+ {
+ await Assert.That(["one", "two"]).Contains(name);
+ await Assert.That(count).IsNotEqualTo(0);
+ }
+}
+
+[AutoMemberDataSource(nameof(Names))]
+public class ClassLevelComplexTypeScenarioTests(
+ string name,
+ PropertyHolder ph,
+ SingleParameterType spt,
+ MyClass sut)
+{
+ public static IEnumerable Names => ["alpha", "beta"];
+
+ [Test]
+ public async Task WhenAppliedToClass_UsesMemberValueAndFillsComplexRemaining()
+ {
+ await Assert.That(["alpha", "beta"]).Contains(name);
+
+ await Assert.That(ph).IsNotNull();
+ await Assert.That(ph.Property).IsNotNull();
+
+ await Assert.That(spt).IsNotNull();
+ await Assert.That(spt.Parameter).IsNotNull();
+
+ await Assert.That(sut).IsNotNull();
+ await Assert.That(sut.Echo(7)).IsEqualTo(7);
+ }
+}
+
+[AutoMemberDataSource(nameof(OneEmptyRow))]
+public class ClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second)
+{
+ public static IEnumerable OneEmptyRow()
+ {
+ yield return [];
+ }
+
+ [Test]
+ public async Task WhenFrozenOnConstructorParameter_SharesInstanceWithLaterParameter()
+ {
+ await Assert.That(second).IsEqualTo(first);
+ }
+}
+
+[AutoMemberDataSource(nameof(OneEmptyRow))]
+public class ClassLevelModestScenarioTests([Modest] MultiUnorderedConstructorType value)
+{
+ public static IEnumerable OneEmptyRow()
+ {
+ yield return [];
+ }
+
+ [Test]
+ public async Task WhenModestOnConstructorParameter_UsesModestConstructor()
+ {
+ await Assert.That(string.IsNullOrEmpty(value.Text)).IsTrue();
+ await Assert.That(value.Number).IsEqualTo(0);
+ }
+}
+
+[AutoMemberDataSource(nameof(Names))]
+public class ClassLevelMultiConstructorParameterizedFirstScenarioTests
+{
+ public static IEnumerable Names => ["from-member"];
+
+ private readonly string name;
+
+ public ClassLevelMultiConstructorParameterizedFirstScenarioTests(string name)
+ {
+ this.name = name;
+ }
+
+ public ClassLevelMultiConstructorParameterizedFirstScenarioTests()
+ {
+ this.name = "parameterless";
+ }
+
+ [Test]
+ public async Task WhenParameterizedConstructorDeclaredFirst_UsesMemberConstructorArgument()
+ {
+ await Assert.That(this.name).IsEqualTo("from-member");
+ }
+}
+
+[AutoMemberDataSource(nameof(Counts))]
+public class ClassLevelMultiConstructorIntFirstScenarioTests
+{
+ public static IEnumerable Counts => [11, 22];
+
+ private readonly string name;
+ private readonly int count;
+
+ public ClassLevelMultiConstructorIntFirstScenarioTests(int count)
+ {
+ this.name = "int-ctor";
+ this.count = count;
+ }
+
+ public ClassLevelMultiConstructorIntFirstScenarioTests(string name)
+ {
+ this.name = name;
+ this.count = -1;
+ }
+
+ [Test]
+ public async Task WhenIntConstructorDeclaredFirst_UsesMemberIntArgument()
+ {
+ await Assert.That(this.name).IsEqualTo("int-ctor");
+ await Assert.That([11, 22]).Contains(this.count);
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs
new file mode 100644
index 0000000..57cd663
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ConstructionTests.cs
@@ -0,0 +1,67 @@
+namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests;
+
+public class ConstructionTests
+{
+ [Test]
+ public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute()
+ {
+ var sut = new AutoMemberDataSourceAttribute(Guid.NewGuid().ToString());
+
+ await Assert.That(sut).IsAssignableTo();
+ }
+
+ [Test]
+ public async Task Constructor_WhenMemberNameAndParameters_SetsMembers()
+ {
+ var memberName = Guid.NewGuid().ToString();
+ object[] parameters = ["value-one", 3, 12.2f];
+
+ var sut = new AutoMemberDataSourceAttribute(memberName, parameters);
+
+ await Assert.That(sut.MemberName).IsEqualTo(memberName);
+ await Assert.That(sut.Parameters).IsEqualTo(parameters);
+ await Assert.That(sut.MemberType).IsNull();
+ await Assert.That(sut.FixtureFactory).IsNotNull();
+ }
+
+ [Test]
+ public async Task Constructor_WhenTypeMemberNameAndParameters_SetsMembers()
+ {
+ var memberName = Guid.NewGuid().ToString();
+ object[] parameters = ["value-one", 3, 12.2f];
+ var testType = typeof(ConstructionTests);
+
+ var sut = new AutoMemberDataSourceAttribute(testType, memberName, parameters);
+
+ await Assert.That(sut.MemberName).IsEqualTo(memberName);
+ await Assert.That(sut.Parameters).IsEqualTo(parameters);
+ await Assert.That(sut.MemberType).IsEqualTo(testType);
+ await Assert.That(sut.FixtureFactory).IsNotNull();
+ }
+
+ [Test]
+ public async Task Constructor_WhenMemberNameIsNull_ThrowsArgumentNullException()
+ {
+ await Assert.That(() => new AutoMemberDataSourceAttribute(null))
+ .ThrowsExactly();
+ }
+
+ [Test]
+ public async Task Constructor_WhenParametersIsNull_TreatsAsSingleNullArgument()
+ {
+ var memberName = Guid.NewGuid().ToString();
+
+ var actual = new AutoMemberDataSourceAttribute(memberName, null);
+
+ var value = await Assert.That(actual.Parameters).HasSingleItem();
+ await Assert.That(value).IsNull();
+ }
+
+ [Test]
+ public void Constructor_WhenMemberTypeIsNull_DoesNotThrow()
+ {
+ var memberName = Guid.NewGuid().ToString();
+
+ _ = new AutoMemberDataSourceAttribute(null, memberName);
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/EmptySequenceRowTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/EmptySequenceRowTests.cs
new file mode 100644
index 0000000..243ddde
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/EmptySequenceRowTests.cs
@@ -0,0 +1,30 @@
+using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests;
+
+///
+/// Empty member sequences cannot be asserted via a [Test] body (no cases run),
+/// so they stay as direct GetData checks.
+///
+public class EmptySequenceRowTests
+{
+ [Test]
+ public async Task GetData_WhenMemberReturnsEmptyObjectArraySequence_YieldsNoRows()
+ {
+ var result = AutoMemberRowCollect.FromMember(
+ nameof(MemberDataShapes.EmptyObjectArrays),
+ nameof(TestTypes.SampleTestType.TestMethodWithTwoParameters));
+
+ await Assert.That(result).IsEmpty();
+ }
+
+ [Test]
+ public async Task GetData_WhenMemberReturnsEmptyAsyncSequence_YieldsNoRows()
+ {
+ var result = AutoMemberRowCollect.FromMember(
+ nameof(MemberDataShapes.EmptyAsyncObjectArrays),
+ nameof(TestTypes.SampleTestType.TestMethodWithTwoParameters));
+
+ await Assert.That(result).IsEmpty();
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs
new file mode 100644
index 0000000..f89532e
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericClassLevelScenarioTests.cs
@@ -0,0 +1,69 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+using ConcreteType = TestTypeFoundation.ConcreteType;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests;
+
+///
+/// Class-level [AutoMemberDataSource<T>] scenarios parallel to the non-generic class-level set.
+///
+[AutoMemberDataSource(nameof(GenericMemberHost.Names))]
+public class GenericClassLevelPrimitiveScenarioTests(string name, int count)
+{
+ [Test]
+ public async Task WhenGenericAppliedToClass_UsesMemberValueAndFillsRemaining()
+ {
+ await Assert.That(["one", "two"]).Contains(name);
+ await Assert.That(count).IsNotEqualTo(0);
+ }
+}
+
+[AutoMemberDataSource(nameof(GenericMemberHost.Names))]
+public class GenericClassLevelComplexTypeScenarioTests(
+ string name,
+ PropertyHolder ph,
+ SingleParameterType spt,
+ MyClass sut)
+{
+ [Test]
+ public async Task WhenGenericAppliedToClass_UsesMemberValueAndFillsComplexRemaining()
+ {
+ await Assert.That(["one", "two"]).Contains(name);
+
+ await Assert.That(ph).IsNotNull();
+ await Assert.That(ph.Property).IsNotNull();
+
+ await Assert.That(spt).IsNotNull();
+ await Assert.That(spt.Parameter).IsNotNull();
+
+ await Assert.That(sut).IsNotNull();
+ await Assert.That(sut.Echo(7)).IsEqualTo(7);
+ }
+}
+
+[AutoMemberDataSource(nameof(OneEmptyRow))]
+public class GenericClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second)
+{
+ public static IEnumerable OneEmptyRow()
+ {
+ yield return [];
+ }
+
+ [Test]
+ public async Task WhenGenericFrozenOnConstructorParameter_SharesInstanceWithLaterParameter()
+ {
+ await Assert.That(second).IsEqualTo(first);
+ }
+}
+
+public class GenericMemberHost
+{
+ public static IEnumerable Names
+ {
+ get
+ {
+ yield return "one";
+ yield return "two";
+ }
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs
new file mode 100644
index 0000000..0706c2b
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GenericUsageScenarioTests.cs
@@ -0,0 +1,99 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests;
+
+///
+/// End-to-end [AutoMemberDataSource<T>] usage parallel to the non-generic scenarios.
+///
+public class GenericUsageScenarioTests
+{
+ [Test, AutoMemberDataSource(nameof(MemberHost.Strings))]
+ public async Task WhenGenericMemberYieldsStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover)
+ {
+ await Assert.That(["one", "two"]).Contains(value);
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test, AutoMemberDataSource(nameof(MemberHost.ObjectArrays))]
+ public async Task WhenGenericMemberReturnsObjectArrays_UsesSuppliedValues(
+ string a, int b, RecordType c)
+ {
+ await Assert.That<(string, int, string)[]>([
+ ("hello", 1, "world"),
+ ("foo", 2, "bar")
+ ]).Contains((a, b, c.Value));
+ }
+
+ [Test, AutoMemberDataSource(nameof(MemberHost.StringData))]
+ public async Task WhenGenericMemberOnHostType_UsesSuppliedValues(string s1, string s2, MyClass leftover)
+ {
+ await Assert.That(s1).IsEqualTo("foo");
+ await Assert.That(s2).IsNotNull();
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test, MyCustomAutoMemberDataSource(nameof(MemberHost.IntData))]
+ public async Task WhenGenericCustomMemberAttribute_SuppliesExtraValues(int x, int y, int z)
+ {
+ await Assert.That(x).IsEqualTo(1337);
+ await Assert.That(y).IsNotEqualTo(0);
+ await Assert.That(z).IsEqualTo(42);
+ }
+
+ public class MemberHost
+ {
+ public static IEnumerable Strings
+ {
+ get
+ {
+ yield return "one";
+ yield return "two";
+ }
+ }
+
+ public static IEnumerable ObjectArrays
+ {
+ get
+ {
+ yield return ["hello", 1, new RecordType("world")];
+ yield return ["foo", 2, new RecordType("bar")];
+ }
+ }
+
+ public static IEnumerable StringData
+ {
+ get
+ {
+ yield return ["foo"];
+ yield return ["foo", "bar"];
+ }
+ }
+
+ public static IEnumerable IntData
+ {
+ get
+ {
+ yield return [1337];
+ yield return [1337, 7];
+ yield return [1337, 7, 42];
+ }
+ }
+ }
+
+ public class MyCustomAutoMemberDataSourceAttribute : AutoMemberDataSourceAttribute
+ {
+ public MyCustomAutoMemberDataSourceAttribute(string memberName, params object[] parameters)
+ : base(() => new Fixture().Customize(new TheAnswer()), memberName, parameters)
+ {
+ }
+ }
+
+ private class TheAnswer : ICustomization
+ {
+ public void Customize(IFixture fixture)
+ {
+ fixture.Inject(42);
+ }
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs
similarity index 56%
rename from tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs
index f49bd1a..c9b5fca 100644
--- a/tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/GetDataTests.cs
@@ -1,132 +1,53 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
+using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport;
using AutoFixture.TUnit.Tests.TestTypes;
using TestTypeFoundation;
-using TUnit.Assertions.Extensions;
using ConcreteType = TestTypeFoundation.ConcreteType;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests;
[SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local",
Justification = "Using parameter for precondition checks is acceptable in assertions.")]
-public class MemberAutoDataSourceAttributeTest
+public class GetDataTests
{
[Test]
- public async Task SutIsDataAttribute()
- {
- // Arrange
- var memberName = Guid.NewGuid().ToString();
-
- // Act
- var sut = new AutoMemberDataSourceAttribute(memberName);
-
- // Assert
- await Assert.That(sut).IsAssignableTo();
- }
-
- [Test]
- public async Task InitializedWithMemberNameAndParameters()
- {
- // Arrange
- var memberName = Guid.NewGuid().ToString();
- var parameters = new object[] { "value-one", 3, 12.2f };
-
- // Act
- var sut = new AutoMemberDataSourceAttribute(memberName, parameters);
-
- // Assert
- await Assert.That(sut.MemberName).IsEqualTo(memberName);
- await Assert.That(sut.Parameters).IsEqualTo(parameters);
- await Assert.That(sut.MemberType).IsNull();
- await Assert.That(sut.FixtureFactory).IsNotNull();
- }
-
- [Test]
- public async Task InitializedWithTypeMemberNameAndParameters()
- {
- // Arrange
- var memberName = Guid.NewGuid().ToString();
- var parameters = new object[] { "value-one", 3, 12.2f };
- var testType = typeof(MemberAutoDataSourceAttributeTest);
-
- // Act
- var sut = new AutoMemberDataSourceAttribute(testType, memberName, parameters);
-
- // Assert
- await Assert.That(sut.MemberName).IsEqualTo(memberName);
- await Assert.That(sut.Parameters).IsEqualTo(parameters);
- await Assert.That(sut.MemberType).IsEqualTo(testType);
- await Assert.That(sut.FixtureFactory).IsNotNull();
- }
-
- [Test]
- public async Task ThrowsWhenInitializedWithNullMemberName()
- {
- // Act & Assert
- await Assert.That(() => new AutoMemberDataSourceAttribute(null!))
- .ThrowsExactly();
- }
-
- [Test]
- public async Task TreatsNullParametersAsArrayWithNullValue()
- {
- // Arrange
- var memberName = Guid.NewGuid().ToString();
-
- // Act
- var actual = new AutoMemberDataSourceAttribute(memberName, null!);
-
- // Act & Assert
- var value = await Assert.That(actual.Parameters).HasSingleItem();
- await Assert.That(value).IsNull();
- }
-
- [Test]
- public void DoesNotThrowWhenInitializedWithNullType()
- {
- // Arrange
- var memberName = Guid.NewGuid().ToString();
-
- // Act & Assert
- _ = new AutoMemberDataSourceAttribute(null!, memberName);
- }
-
- [Test]
- public void ThrowsWhenTestMethodNull()
+ public void GetData_WhenTestMethodNull_Throws()
{
// Arrange
var sut = new AutoMemberDataSourceAttribute("memberName");
// Act & Assert
Assert.Throws(
- () => _ = sut.GenerateDataSources(null!).Select(x => x()).ToArray());
+ () => _ = sut.GenerateDataSources(null).Select(x => x()).ToArray());
}
[Test]
- public async Task ThrowsWhenMemberNotEnumerable()
+ public async Task GetData_WhenMemberReturnsScalar_ReturnsData()
{
// Arrange
const string memberName = nameof(TestTypeWithMethodData.NonEnumerableMethod);
var sut = new AutoMemberDataSourceAttribute(memberName);
var method = TestTypeWithMethodData.GetMultipleValueTestMethodInfo();
var dataGeneratorMetadata = DataGeneratorMetadataHelper
- .CreateDataGeneratorMetadata(method!);
+ .CreateDataGeneratorMetadata(method);
- // Act & Assert
- var ex = Assert.Throws(
- () => sut.GenerateDataSources(dataGeneratorMetadata).ToArray());
+ // Act
+ var result = sut.GenerateDataSources(dataGeneratorMetadata).Select(x => x()).ToArray();
- await Assert.That(ex.Message).Contains(memberName);
+ // Assert — scalar becomes one row; remaining parameters are auto-generated
+ await Assert.That(result.Length).IsEqualTo(1);
+ await Assert.That(result[0].Length).IsEqualTo(method.GetParameters().Length);
}
[Test]
- public async Task ThrowsWhenMemberNotStatic()
+ public async Task GetData_WhenMemberNotStatic_Throws()
{
// Arrange
const string memberName = nameof(TestTypeWithMethodData.NonStaticSource);
var sut = new AutoMemberDataSourceAttribute(memberName);
var method = TestTypeWithMethodData.GetMultipleValueTestMethodInfo();
var dataGeneratorMetadata = DataGeneratorMetadataHelper
- .CreateDataGeneratorMetadata(method!);
+ .CreateDataGeneratorMetadata(method);
// Act & Assert
var ex = Assert.Throws(
@@ -136,14 +57,14 @@ public async Task ThrowsWhenMemberNotStatic()
}
[Test]
- public async Task ThrowsWhenMemberDoesNotExist()
+ public async Task GetData_WhenMemberDoesNotExist_Throws()
{
// Arrange
var memberName = Guid.NewGuid().ToString();
var sut = new AutoMemberDataSourceAttribute(typeof(TestTypeWithMethodData), memberName);
var method = TestTypeWithMethodData.GetMultipleValueTestMethodInfo();
var dataGeneratorMetadata = DataGeneratorMetadataHelper
- .CreateDataGeneratorMetadata(method!);
+ .CreateDataGeneratorMetadata(method);
// Act & Assert
var ex = Assert.Throws(
@@ -152,7 +73,7 @@ public async Task ThrowsWhenMemberDoesNotExist()
}
[Test]
- public async Task DoesntActivateFixtureImmediately()
+ public async Task Constructor_WhenCreated_DoesNotActivateFixtureImmediately()
{
// Arrange
var memberName = Guid.NewGuid().ToString();
@@ -182,18 +103,18 @@ public async Task DoesntActivateFixtureImmediately()
[Arguments("CreateWithModestAndFrozen")]
[Arguments("CreateWithFrozenAndNoAutoProperties")]
[Arguments("CreateWithNoAutoPropertiesAndFrozen")]
- public async Task GetDataOrdersCustomizationAttributes(string methodName)
+ public async Task GetData_WhenCustomizationsPresent_OrdersThem(string methodName)
{
// Arrange
var method = typeof(TypeWithCustomizationAttributes)
- .GetMethod(methodName, [typeof(ConcreteType)])!;
+ .GetMethod(methodName, [typeof(ConcreteType)]);
var customizationLog = new List();
var fixture = new DelegatingFixture
{
OnCustomize = c => customizationLog.Add(c)
};
var dataGeneratorMetadata = DataGeneratorMetadataHelper
- .CreateDataGeneratorMetadata(method!);
+ .CreateDataGeneratorMetadata(method);
var sut = new DerivedAutoMemberDataSourceAttribute(
() => fixture,
typeof(TestTypeWithMethodData),
@@ -211,20 +132,19 @@ public async Task GetDataOrdersCustomizationAttributes(string methodName)
}
[Test]
- public async Task GeneratesTestsFromParameterlessMethod()
+ public async Task GetData_WhenParameterlessMethod_GeneratesTests()
{
// Arrange
const string memberName = nameof(TestTypeWithMethodData.GetSingleStringValueTestData);
var sut = new AutoMemberDataSourceAttribute(memberName);
var testMethod = TestTypeWithMethodData.GetSingleStringValueTestMethodInfo();
var dataGeneratorMetadata = DataGeneratorMetadataHelper
- .CreateDataGeneratorMetadata(testMethod!);
- var expected = new[]
- {
- new object[] { "value-one" },
- new object[] { "value-two" },
- new object[] { "value-three" }
- };
+ .CreateDataGeneratorMetadata(testMethod);
+ object[][] expected = [
+ [ "value-one" ],
+ ["value-two"],
+ ["value-three"]
+ ];
// Act
var testData = sut.GenerateDataSources(dataGeneratorMetadata)
@@ -236,20 +156,19 @@ public async Task GeneratesTestsFromParameterlessMethod()
}
[Test]
- public async Task GeneratesTestsFromMethodWithParameter()
+ public async Task GetData_WhenMethodWithParameter_GeneratesTests()
{
// Arrange
const string memberName = nameof(TestTypeWithMethodData.GetStringTestsFromArgument);
var sut = new AutoMemberDataSourceAttribute(memberName, "value");
var testMethod = TestTypeWithMethodData.GetStringTestsFromArgumentMethodInfo();
var dataGeneratorMetadata = DataGeneratorMetadataHelper
- .CreateDataGeneratorMetadata(testMethod!);
- var expected = new[]
- {
- new object[] { "value-one" },
- new object[] { "value-two" },
- new object[] { "value-three" }
- };
+ .CreateDataGeneratorMetadata(testMethod);
+ object[][] expected = [
+ [ "value-one" ],
+ ["value-two"],
+ ["value-three"]
+ ];
// Act
var testData = sut.GenerateDataSources(dataGeneratorMetadata)
@@ -259,20 +178,19 @@ public async Task GeneratesTestsFromMethodWithParameter()
}
[Test]
- public async Task GeneratesTestDataForTestsWithMultipleParameters()
+ public async Task GetData_WhenMultipleParameters_GeneratesTestData()
{
// Arrange
const string memberName = nameof(TestTypeWithMethodData.GetMultipleValueTestData);
var sut = new AutoMemberDataSourceAttribute(memberName);
var testMethod = TestTypeWithMethodData.GetMultipleValueTestMethodInfo();
var dataGeneratorMetadata = DataGeneratorMetadataHelper
- .CreateDataGeneratorMetadata(testMethod!);
- var expected = new[]
- {
- new object[] { "value-one", 12, 23.3m },
- new object[] { "value-two", 38, 12.7m },
- new object[] { "value-three", 94, 52.21m }
- };
+ .CreateDataGeneratorMetadata(testMethod);
+ object[][] expected = [
+ [ "value-one", 12, 23.3m ],
+ ["value-two", 38, 12.7m],
+ ["value-three", 94, 52.21m]
+ ];
// Act
var testData = sut.GenerateDataSources(dataGeneratorMetadata)
@@ -283,14 +201,14 @@ public async Task GeneratesTestDataForTestsWithMultipleParameters()
}
[Test]
- public async Task GeneratesMissingDataForTestsWithMultipleParameters()
+ public async Task GetData_WhenMultipleParametersPartial_GeneratesMissingData()
{
// Arrange
const string memberName = nameof(TestTypeWithMethodData.GetSingleStringValueTestData);
var sut = new AutoMemberDataSourceAttribute(memberName);
var testMethod = TestTypeWithMethodData.GetMultipleValueTestMethodInfo();
var dataGeneratorMetadata = DataGeneratorMetadataHelper
- .CreateDataGeneratorMetadata(testMethod!);
+ .CreateDataGeneratorMetadata(testMethod);
// Act
var testData = sut.GenerateDataSources(dataGeneratorMetadata)
@@ -302,36 +220,35 @@ public async Task GeneratesMissingDataForTestsWithMultipleParameters()
// Assert
await Assert.That(arguments1.Length).IsEqualTo(3);
- await Assert.That(arguments1[0]).IsEqualTo("value-one");
- await Assert.That(arguments1[1]).IsNotEqualTo(0);
- await Assert.That(arguments1[2]).IsNotEqualTo(0);
+ await Assert.That((string)arguments1[0]).IsEqualTo("value-one");
+ await Assert.That((int)arguments1[1]).IsNotEqualTo(0);
+ await Assert.That((decimal)arguments1[2]).IsNotEqualTo(0m);
await Assert.That(arguments2.Length).IsEqualTo(3);
- await Assert.That(arguments2[0]).IsEqualTo("value-two");
- await Assert.That(arguments2[1]).IsNotEqualTo(0);
- await Assert.That(arguments2[2]).IsNotEqualTo(0);
+ await Assert.That((string)arguments2[0]).IsEqualTo("value-two");
+ await Assert.That((int)arguments2[1]).IsNotEqualTo(0);
+ await Assert.That((decimal)arguments2[2]).IsNotEqualTo(0m);
await Assert.That(arguments3.Length).IsEqualTo(3);
- await Assert.That(arguments3[0]).IsEqualTo("value-three");
- await Assert.That(arguments3[1]).IsNotEqualTo(0);
- await Assert.That(arguments3[2]).IsNotEqualTo(0);
+ await Assert.That((string)arguments3[0]).IsEqualTo("value-three");
+ await Assert.That((int)arguments3[1]).IsNotEqualTo(0);
+ await Assert.That((decimal)arguments3[2]).IsNotEqualTo(0m);
}
[Test]
- public async Task GeneratesTestDataWithInjectedParameters()
+ public async Task GetData_WhenInjectedParameters_GeneratesTestData()
{
// Arrange
const string memberName = nameof(TestTypeWithMethodData.GetDataForTestWithFrozenParameter);
var sut = new AutoMemberDataSourceAttribute(memberName);
var testMethod = TestTypeWithMethodData.GetTestWithFrozenParameter();
var dataGeneratorMetadata = DataGeneratorMetadataHelper
- .CreateDataGeneratorMetadata(testMethod!);
- var expected = new[]
- {
- new object[] { "value-one", "value-two", "value-two" },
- new object[] { "value-two", "value-three", "value-three" },
- new object[] { "value-three", "value-one", "value-one" }
- };
+ .CreateDataGeneratorMetadata(testMethod);
+ object[][] expected = [
+ [ "value-one", "value-two", "value-two" ],
+ ["value-two", "value-three", "value-three"],
+ ["value-three", "value-one", "value-one"]
+ ];
// Act
var testData = sut.GenerateDataSources(dataGeneratorMetadata)
@@ -342,13 +259,13 @@ public async Task GeneratesTestDataWithInjectedParameters()
}
[Test]
- public async Task AutoGeneratesValuesForFrozenParameters()
+ public async Task GetData_WhenFrozenParameters_AutoGeneratesValues()
{
// Arrange
const string memberName = nameof(TestTypeWithMethodData.GetSingleStringValueTestData);
var sut = new AutoMemberDataSourceAttribute(memberName);
var testMethod = TestTypeWithMethodData.GetTestWithFrozenParameter();
- var dataGeneratorMetadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!);
+ var dataGeneratorMetadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod);
// Act
var testData = sut.GenerateDataSources(dataGeneratorMetadata)
@@ -360,35 +277,34 @@ public async Task AutoGeneratesValuesForFrozenParameters()
// Assert
await Assert.That(arguments1.Length).IsEqualTo(3);
- await Assert.That(arguments1[0]).IsEqualTo("value-one");
- await Assert.That(arguments1[1].ToString()!).IsNotEmpty();
- await Assert.That(arguments1[2]).IsEqualTo(arguments1[1]);
+ await Assert.That((string)arguments1[0]).IsEqualTo("value-one");
+ await Assert.That(arguments1[1].ToString()).IsNotEmpty();
+ await Assert.That(arguments1[2]).IsSameReferenceAs(arguments1[1]);
await Assert.That(arguments2.Length).IsEqualTo(3);
- await Assert.That(arguments2[0]).IsEqualTo("value-two");
- await Assert.That(arguments2[1].ToString()!).IsNotEmpty();
- await Assert.That(arguments2[2]).IsEqualTo(arguments2[1]);
+ await Assert.That((string)arguments2[0]).IsEqualTo("value-two");
+ await Assert.That(arguments2[1].ToString()).IsNotEmpty();
+ await Assert.That(arguments2[2]).IsSameReferenceAs(arguments2[1]);
await Assert.That(arguments3.Length).IsEqualTo(3);
- await Assert.That(arguments3[0]).IsEqualTo("value-three");
- await Assert.That(arguments3[1].ToString()!).IsNotEmpty();
- await Assert.That(arguments3[2]).IsEqualTo(arguments3[1]);
+ await Assert.That((string)arguments3[0]).IsEqualTo("value-three");
+ await Assert.That(arguments3[1].ToString()).IsNotEmpty();
+ await Assert.That(arguments3[2]).IsSameReferenceAs(arguments3[1]);
}
[Test]
- public async Task SupportsInheritedTestDataMembers()
+ public async Task GetData_WhenMemberInherited_SupportsMember()
{
// Arrange
const string memberName = nameof(TestTypeWithMethodData.GetMultipleValueTestData);
var sut = new AutoMemberDataSourceAttribute(memberName);
var testMethod = ChildTestTypeMethodData.GetMultipleValueTestMethodInfo();
- var expected = new[]
- {
- new object[] { "value-one", 12, 23.3m },
- new object[] { "value-two", 38, 12.7m },
- new object[] { "value-three", 94, 52.21m }
- };
- var dataGeneratorMetadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!);
+ object[][] expected = [
+ [ "value-one", 12, 23.3m ],
+ ["value-two", 38, 12.7m],
+ ["value-three", 94, 52.21m]
+ ];
+ var dataGeneratorMetadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod);
// Act
var testData = sut.GenerateDataSources(dataGeneratorMetadata)
@@ -402,18 +318,18 @@ public static IEnumerable TestDataWithNullValues
{
get
{
- yield return [null!, null!];
- yield return [string.Empty, null!];
- yield return [" ", null!];
+ yield return [null, null];
+ yield return [string.Empty, null];
+ yield return [" ", null];
}
}
[Test]
[AutoMemberDataSource(nameof(TestDataWithNullValues))]
- public async Task NullTestDataReturned(string a, string b, PropertyHolder c)
+ public async Task WhenMemberReturnsNullRows_ReceivesNullValues(string a, string b, PropertyHolder c)
{
await Assert.That(string.IsNullOrWhiteSpace(a)).IsTrue();
await Assert.That(b).IsNull();
await Assert.That(c).IsNotNull();
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs
new file mode 100644
index 0000000..6e415f6
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ResultShapeScenarioTests.cs
@@ -0,0 +1,135 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures;
+using TestTypeFoundation;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests;
+
+///
+/// End-to-end [AutoMemberDataSource] coverage for README result shapes.
+///
+public class ResultShapeScenarioTests
+{
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.ObjectArrays))]
+ public async Task WhenMemberReturnsObjectArrays_UsesSuppliedValues(
+ string a, int b, RecordType c)
+ {
+ await Assert.That<(string, int, string)[]>([
+ ("hello", 1, "world"),
+ ("foo", 2, "bar")
+ ]).Contains((a, b, c.Value));
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.Strings))]
+ public async Task WhenMemberYieldsStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover)
+ {
+ await Assert.That(["one", "two"]).Contains(value);
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.StringScalar))]
+ public async Task WhenMemberReturnsStringScalar_ReceivesValueAndFillsRemaining(string value, MyClass leftover)
+ {
+ await Assert.That(value).IsEqualTo("hello");
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.ObjectScalar))]
+ public async Task WhenMemberReturnsObjectScalar_ReceivesValueAndFillsRemaining(object value, MyClass leftover)
+ {
+ await Assert.That(value).IsNotNull();
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.Tuples))]
+ public async Task WhenMemberYieldsTuples_ExpandsColumnsAndFillsRemaining(
+ string left, int right, MyClass leftover)
+ {
+ await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right));
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.SingleTuple))]
+ public async Task WhenMemberReturnsSingleTuple_ExpandsColumnsAndFillsRemaining(
+ string left, int right, MyClass leftover)
+ {
+ await Assert.That(left).IsEqualTo("a");
+ await Assert.That(right).IsEqualTo(1);
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.NullValue))]
+ public async Task WhenMemberReturnsNull_ReceivesNullCellAndFillsRemaining(string value, MyClass leftover)
+ {
+ await Assert.That(value).IsNull();
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.TaskOfObjectArrays))]
+ public async Task WhenMemberReturnsTaskOfObjectArrays_UsesSuppliedValues(
+ string a, int b, RecordType c)
+ {
+ await Assert.That<(string, int, string)[]>([
+ ("hello", 1, "world"),
+ ("foo", 2, "bar")
+ ]).Contains((a, b, c.Value));
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.TaskOfTuples))]
+ public async Task WhenMemberReturnsTaskOfTuples_ExpandsColumnsAndFillsRemaining(
+ string left, int right, MyClass leftover)
+ {
+ await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right));
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.AsyncObjectArrays))]
+ public async Task WhenMemberReturnsAsyncObjectArrays_UsesSuppliedValues(
+ string a, int b, RecordType c)
+ {
+ await Assert.That<(string, int, string)[]>([
+ ("hello", 1, "world"),
+ ("foo", 2, "bar")
+ ]).Contains((a, b, c.Value));
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.AsyncStrings))]
+ public async Task WhenMemberReturnsAsyncStrings_ReceivesValueAndFillsRemaining(string value, MyClass leftover)
+ {
+ await Assert.That(["one", "two"]).Contains(value);
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.AsyncTuples))]
+ public async Task WhenMemberReturnsAsyncTuples_ExpandsColumnsAndFillsRemaining(
+ string left, int right, MyClass leftover)
+ {
+ await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right));
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.TupleField))]
+ public async Task WhenMemberIsTupleField_ExpandsColumns(string left, int right)
+ {
+ await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right));
+ }
+
+ [Test]
+ [AutoMemberDataSource(typeof(MemberDataShapes), nameof(MemberDataShapes.TupleProperty))]
+ public async Task WhenMemberIsTupleProperty_ExpandsColumns(string left, int right)
+ {
+ await Assert.That<(string, int)[]>([("a", 1), ("b", 2)]).Contains((left, right));
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ScenarioTests.cs
similarity index 90%
rename from tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeScenarioTests.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ScenarioTests.cs
index 3ad18dd..2551e82 100644
--- a/tests/AutoFixture.TUnit.Tests/MemberAutoDataSourceAttributeScenarioTests.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/ScenarioTests.cs
@@ -1,7 +1,7 @@
using AutoFixture.TUnit.Tests.TestTypes;
using TestTypeFoundation;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests;
public class MemberAutoDataSourceAttributeScenarioTests
{
@@ -17,7 +17,7 @@ public class MemberAutoDataSourceAttributeScenarioTests
memberType: typeof(TestTypeWithMethodData),
memberName: nameof(TestTypeWithMethodData.GetStringTestsFromArgument),
parameters: "argument")]
- public async Task SingleStringValueTest(string value)
+ public async Task WhenSingleStringMember_ReceivesStringValue(string value)
{
await Assert.That(value).IsNotNull();
await Assert.That(value).IsNotEmpty();
@@ -29,7 +29,7 @@ public async Task SingleStringValueTest(string value)
[AutoMemberDataSource(
memberType: typeof(TestTypeWithMethodData),
memberName: nameof(TestTypeWithMethodData.GetMultipleValueTestData))]
- public async Task MultipleValueTest(string a, int b, decimal c)
+ public async Task WhenMultipleValueMember_ReceivesExpectedValues(string a, int b, decimal c)
{
await Assert.That(a).IsNotNull();
await Assert.That(a).IsNotEmpty();
@@ -44,7 +44,7 @@ public async Task MultipleValueTest(string a, int b, decimal c)
[AutoMemberDataSource(
memberType: typeof(TestTypeWithMethodData),
memberName: nameof(TestTypeWithMethodData.GetSingleStringValueTestData))]
- public async Task FreezesUninjectedValues(
+ public async Task WhenUninjectedValuesFrozen_SubsequentMatch(
string a, [Frozen] string b, string c,
PropertyHolder d)
{
@@ -64,7 +64,7 @@ public async Task FreezesUninjectedValues(
[Test]
[AutoMemberDataSource(nameof(GetMultipleValueTestData))]
- public async Task InjectsValues([Frozen] string a,
+ public async Task WhenMemberValuesProvided_InjectsValues([Frozen] string a,
[Frozen] int b,
[Frozen] decimal c,
PropertyHolder a1,
@@ -93,7 +93,7 @@ public async Task InjectsValues([Frozen] string a,
[AutoMemberDataSource(
memberType: typeof(TestTypeWithMethodData),
memberName: nameof(TestTypeWithMethodData.GetStringValuesTestData))]
- public async Task DoesNotAlterTestDataValuesWhenFrozen(
+ public async Task WhenFrozen_DoesNotAlterMemberDataValues(
[Frozen] string a, string b, string c)
{
var aSuffix = a.Split('-').Last();
@@ -110,7 +110,7 @@ public async Task DoesNotAlterTestDataValuesWhenFrozen(
[AutoMemberDataSource(
memberType: typeof(TestTypeWithMethodData),
memberName: nameof(TestTypeWithMethodData.GetStringValuesTestData))]
- public async Task LastInjectedValueIsFrozen(
+ public async Task WhenLastInjectedValueFrozen_SubsequentMatch(
[Frozen] string a, [Frozen] string b, string c)
{
var aSuffix = a.Split('-').Last();
@@ -126,7 +126,7 @@ public async Task LastInjectedValueIsFrozen(
[AutoMemberDataSource(
memberType: typeof(TestTypeWithMethodData),
memberName: nameof(TestTypeWithMethodData.GetTestWithComplexTypesData))]
- public async Task InjectsComplexTypes(
+ public async Task WhenComplexTypes_InjectsExpectedValues(
[Frozen] PropertyHolder a,
PropertyHolder b,
PropertyHolder c)
@@ -158,4 +158,4 @@ public static IEnumerable GetStringValuesTestData()
yield return ["test-two", "test-dos"];
yield return ["test-three", "test-tres"];
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/UsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/UsageScenarioTests.cs
new file mode 100644
index 0000000..4cf4aa9
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/AutoMemberDataSourceAttributeTests/UsageScenarioTests.cs
@@ -0,0 +1,97 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+
+namespace AutoFixture.TUnit.Tests.Attributes.AutoMemberDataSourceAttributeTests;
+
+///
+/// End-to-end [AutoMemberDataSource] usage moved from the old Scenarios bucket.
+///
+public class UsageScenarioTests
+{
+ [Test, AutoMemberDataSource(nameof(StringData))]
+ public async Task WhenMemberSuppliesValues_UsesSuppliedValues(string s1, string s2)
+ {
+ await Assert.That(s1).IsEqualTo("foo");
+ await Assert.That(s2).IsNotNull();
+ }
+
+ [Test, AutoMemberDataSource(nameof(StringData))]
+ public async Task WhenMemberValuesPartial_SuppliesRemainingSpecimens(string s1, string s2, MyClass myClass)
+ {
+ await Assert.That(s1).IsEqualTo("foo");
+ await Assert.That(s2).IsNotNull();
+ await Assert.That(myClass).IsNotNull();
+ }
+
+ [Test, AutoMemberDataSource(nameof(StringData))]
+ public async Task WhenMemberValuesPartial_DoesNotOverwriteSuppliedValues(string s1, string s2, string s3)
+ {
+ await Assert.That(s1).IsEqualTo("foo");
+ await Assert.That(s2).IsNotNull();
+ await Assert.That(s3).IsNotEqualTo("foo");
+ await Assert.That(s3).IsNotEqualTo("bar");
+ }
+
+ [Test, AutoMemberDataSource(nameof(GetParametrizedData), 21, 38, 43)]
+ public async Task WhenMemberDataParameterized_ReceivesExpectedData(int x, int y, int z)
+ {
+ await Assert.That(x).IsEqualTo(21);
+ await Assert.That(y).IsEqualTo(38);
+ await Assert.That(z).IsEqualTo(43);
+ }
+
+ [Test, MyCustomAutoMemberDataSource(nameof(IntData))]
+ public async Task WhenCustomMemberAttribute_SuppliesExtraValues(int x, int y, int z)
+ {
+ await Assert.That(x).IsEqualTo(1337);
+ await Assert.That(y).IsNotEqualTo(0);
+ await Assert.That(z).IsEqualTo(42);
+ }
+
+ [Test, MyCustomAutoMemberDataSource(nameof(GetParametrizedData), 21, 38, 43)]
+ public async Task WhenCustomMemberAttributeParameterized_ReceivesExpectedData(int x, int y, int z)
+ {
+ await Assert.That(x).IsEqualTo(21);
+ await Assert.That(y).IsEqualTo(38);
+ await Assert.That(z).IsEqualTo(43);
+ }
+
+ public static IEnumerable StringData
+ {
+ get
+ {
+ yield return ["foo"];
+ yield return ["foo", "bar"];
+ }
+ }
+
+ public static IEnumerable IntData
+ {
+ get
+ {
+ yield return [1337];
+ yield return [1337, 7];
+ yield return [1337, 7, 42];
+ }
+ }
+
+ public static IEnumerable GetParametrizedData(int x, int y, int z)
+ {
+ yield return [x, y, z];
+ }
+
+ public class MyCustomAutoMemberDataSourceAttribute : AutoMemberDataSourceAttribute
+ {
+ public MyCustomAutoMemberDataSourceAttribute(string memberName, params object[] parameters)
+ : base(() => new Fixture().Customize(new TheAnswer()), memberName, parameters)
+ {
+ }
+ }
+
+ private class TheAnswer : ICustomization
+ {
+ public void Customize(IFixture fixture)
+ {
+ fixture.Inject(42);
+ }
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ClassLevelScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ClassLevelScenarioTests.cs
new file mode 100644
index 0000000..225a65c
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ClassLevelScenarioTests.cs
@@ -0,0 +1,185 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+using ConcreteType = TestTypeFoundation.ConcreteType;
+
+namespace AutoFixture.TUnit.Tests.Attributes.CompositeDataSourceAttributeTests;
+
+///
+/// End-to-end [CompositeDataSource] on the test class (TUnit ClassParameters).
+/// Ordered simple → complex; mirrors AutoDataSource class-level scenarios.
+///
+[ClassLevelPrimitiveComposite]
+public class ClassLevelPrimitiveScenarioTests(string name, int count)
+{
+ [Test]
+ public async Task WhenAppliedToClass_UsesCompositeValues()
+ {
+ await Assert.That(name).IsEqualTo("seed");
+ await Assert.That(count).IsEqualTo(7);
+ }
+}
+
+[ClassLevelComplexComposite]
+public class ClassLevelComplexTypeScenarioTests(
+ string name,
+ PropertyHolder ph,
+ SingleParameterType spt,
+ MyClass sut)
+{
+ [Test]
+ public async Task WhenAppliedToClass_UsesInlineValueAndFillsComplexRemaining()
+ {
+ await Assert.That(name).IsEqualTo("seed");
+
+ await Assert.That(ph).IsNotNull();
+ await Assert.That(ph.Property).IsNotNull();
+
+ await Assert.That(spt).IsNotNull();
+ await Assert.That(spt.Parameter).IsNotNull();
+
+ await Assert.That(sut).IsNotNull();
+ await Assert.That(sut.Echo(7)).IsEqualTo(7);
+ }
+}
+
+[ClassLevelAutoDataComposite]
+public class ClassLevelFrozenScenarioTests([Frozen] Guid first, Guid second)
+{
+ [Test]
+ public async Task WhenFrozenOnConstructorParameter_SharesInstanceWithLaterParameter()
+ {
+ await Assert.That(second).IsEqualTo(first);
+ }
+}
+
+[ClassLevelAutoDataComposite]
+public class ClassLevelModestScenarioTests([Modest] MultiUnorderedConstructorType value)
+{
+ [Test]
+ public async Task WhenModestOnConstructorParameter_UsesModestConstructor()
+ {
+ await Assert.That(string.IsNullOrEmpty(value.Text)).IsTrue();
+ await Assert.That(value.Number).IsEqualTo(0);
+ }
+}
+
+[ClassLevelInlineNameComposite]
+public class ClassLevelMultiConstructorParameterizedFirstScenarioTests
+{
+ private readonly string name;
+
+ public ClassLevelMultiConstructorParameterizedFirstScenarioTests(string name)
+ {
+ this.name = name;
+ }
+
+ public ClassLevelMultiConstructorParameterizedFirstScenarioTests()
+ {
+ this.name = "parameterless";
+ }
+
+ [Test]
+ public async Task WhenParameterizedConstructorDeclaredFirst_UsesCompositeConstructorArgument()
+ {
+ await Assert.That(this.name).IsEqualTo("from-composite");
+ }
+}
+
+[ClassLevelInlineIntComposite]
+public class ClassLevelMultiConstructorIntFirstScenarioTests
+{
+ private readonly string name;
+ private readonly int count;
+
+ public ClassLevelMultiConstructorIntFirstScenarioTests(int count)
+ {
+ this.name = "int-ctor";
+ this.count = count;
+ }
+
+ public ClassLevelMultiConstructorIntFirstScenarioTests(string name)
+ {
+ this.name = name;
+ this.count = -1;
+ }
+
+ [Test]
+ public async Task WhenIntConstructorDeclaredFirst_UsesCompositeIntArgument()
+ {
+ await Assert.That(this.name).IsEqualTo("int-ctor");
+ await Assert.That(this.count).IsEqualTo(42);
+ }
+}
+
+public sealed class ClassLevelPrimitiveCompositeAttribute : CompositeDataSourceAttribute
+{
+ public ClassLevelPrimitiveCompositeAttribute()
+ : base(
+ new FixedRowsAttribute(["seed"]),
+ new FixedRowsAttribute([null!, 7]))
+ {
+ }
+}
+
+public sealed class ClassLevelComplexCompositeAttribute : CompositeDataSourceAttribute
+{
+ public ClassLevelComplexCompositeAttribute()
+ : base(
+ new AutoArgumentsAttribute("seed"),
+ new AutoDataSourceAttribute())
+ {
+ }
+}
+
+public sealed class ClassLevelAutoDataCompositeAttribute : CompositeDataSourceAttribute
+{
+ public ClassLevelAutoDataCompositeAttribute()
+ : base(new AutoDataSourceAttribute())
+ {
+ }
+}
+
+public sealed class ClassLevelInlineNameCompositeAttribute : CompositeDataSourceAttribute
+{
+ public ClassLevelInlineNameCompositeAttribute()
+ : base(
+ new AutoArgumentsAttribute("from-composite"),
+ new FixedRowsAttribute(["ignored"]))
+ {
+ }
+}
+
+public sealed class ClassLevelInlineIntCompositeAttribute : CompositeDataSourceAttribute
+{
+ public ClassLevelInlineIntCompositeAttribute()
+ : base(
+ new AutoArgumentsAttribute(42),
+ new FixedRowsAttribute([0]))
+ {
+ }
+}
+
+///
+/// Yields fixed rows without AutoFixture fill — same public extension model as UsageScenarioTests.
+///
+public sealed class FixedRowsAttribute : BaseDataSourceAttribute
+{
+ private readonly object?[][] rows;
+
+ public FixedRowsAttribute(params object?[][] rows)
+ {
+ this.rows = rows;
+ }
+
+#pragma warning disable CS1998
+ public override async IAsyncEnumerable>> GetData(
+ DataGeneratorMetadata dataGeneratorMetadata)
+ {
+ foreach (var row in this.rows)
+ {
+ var captured = row;
+ yield return () => Task.FromResult(captured);
+ }
+ }
+#pragma warning restore CS1998
+}
diff --git a/tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ConstructionTests.cs
similarity index 66%
rename from tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ConstructionTests.cs
index 08bcb11..b796d96 100644
--- a/tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/ConstructionTests.cs
@@ -1,13 +1,13 @@
-using System.Reflection;
+using System.Reflection;
+using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport;
using AutoFixture.TUnit.Tests.TestTypes;
-using TUnit.Assertions.Extensions;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.CompositeDataSourceAttributeTests;
public class CompositeDataSourceAttributeTest
{
[Test]
- public async Task SutIsDataAttribute()
+ public async Task Constructor_WhenCreated_IsBaseDataSourceAttribute()
{
// Arrange & Act
var sut = new CompositeDataSourceAttribute();
@@ -17,16 +17,16 @@ public async Task SutIsDataAttribute()
}
[Test]
- public async Task InitializeWithNullArrayThrows()
+ public async Task Constructor_WhenArrayIsNull_Throws()
{
// Arrange
// Act & assert
- await Assert.That(() => new CompositeDataSourceAttribute(null!))
+ await Assert.That(() => new CompositeDataSourceAttribute(null))
.ThrowsExactly();
}
[Test]
- public async Task AttributesIsCorrectWhenInitializedWithArray()
+ public async Task Attributes_WhenInitializedWithArray_ReturnsSameAttributes()
{
// Arrange
var a = () => { };
@@ -47,21 +47,22 @@ public async Task AttributesIsCorrectWhenInitializedWithArray()
}
[Test]
- public void InitializeWithNullEnumerableThrows()
+ public void Constructor_WhenEnumerableIsNull_Throws()
{
// Act & assert
Assert.Throws(
- () => _ = new CompositeDataSourceAttribute(((IEnumerable)null)!));
+ () => _ = new CompositeDataSourceAttribute(((IEnumerable)null)));
}
[Test]
- public async Task AttributesIsCorrectWhenInitializedWithEnumerable()
+ public async Task Attributes_WhenInitializedWithEnumerable_ReturnsSameAttributes()
{
// Arrange
var a = () => { };
var method = a.GetMethodInfo();
- var attributes = new BaseDataSourceAttribute[]
+ // Use a List so the IEnumerable ctor cannot cast to array and must call ToArray().
+ IEnumerable attributes = new List
{
new FakeDataAttribute(method, []),
new FakeDataAttribute(method, []),
@@ -76,18 +77,22 @@ public async Task AttributesIsCorrectWhenInitializedWithEnumerable()
}
[Test]
- public async Task GetDataWithNullGeneratorMetadataThrows()
+ public async Task GetData_WhenGeneratorMetadataIsNull_Throws()
{
// Arrange
var sut = new CompositeDataSourceAttribute();
- // Act & assert
- await Assert.That(() => sut.GenerateDataSources(null!)
- .Select(x => x()).ToArray()).ThrowsException();
+ // Act & assert - call GetData directly so the attribute's own null guard is hit
+ await Assert.That(async () =>
+ {
+ await foreach (var _ in sut.GetData(null))
+ {
+ }
+ }).ThrowsExactly();
}
[Test]
- public async Task GetDataOnMethodWithNoParametersReturnsNoTheory()
+ public async Task GetData_WhenMethodHasNoParameters_ReturnsNoRows()
{
// Arrange
var a = () => { };
@@ -106,4 +111,4 @@ public async Task GetDataOnMethodWithNoParametersReturnsNoTheory()
// Assert
await Assert.That(result).All().Satisfy(row => row.IsEmpty());
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeSufficientDataTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/GetDataTests.cs
similarity index 94%
rename from tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeSufficientDataTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/GetDataTests.cs
index 36e3d05..131ee11 100644
--- a/tests/AutoFixture.TUnit.Tests/CompositeDataSourceAttributeSufficientDataTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/GetDataTests.cs
@@ -1,10 +1,10 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
+using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport;
using AutoFixture.TUnit.Tests.TestTypes;
using TestTypeFoundation;
-using TUnit.Assertions.Extensions;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.CompositeDataSourceAttributeTests;
[SuppressMessage("Usage", "TUnit0014:Method should have a `Test` attribute or be made `private` or `protected`")]
[SuppressMessage("Usage", "TUnit0046:Return a `Func` rather than a ``")]
@@ -16,7 +16,7 @@ public class CompositeDataSourceAttributeSufficientDataTest
[Test]
[MethodDataSource(typeof(CompositeDataSourceAttributeSufficientDataTest), nameof(GetEnumerator))]
- public async Task GetDataReturnsCorrectResult(
+ public async Task GetData_WhenCalled_ReturnsCorrectResult(
IEnumerable attributes,
IEnumerable expectedResult)
{
@@ -145,7 +145,7 @@ await Assert.That(result)
]);
// Test incorrect number of parameters - should just return what it's given
- // and let xUnit deal with counting parameters
+ // and let the test runner deal with counting parameters
yield return CreateTestData(
data:
[
@@ -200,4 +200,4 @@ private static (
{
return (data, expected);
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs
new file mode 100644
index 0000000..e352226
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/CompositeDataSourceAttributeTests/UsageScenarioTests.cs
@@ -0,0 +1,84 @@
+using AutoFixture.TUnit.Tests.TestTypes;
+
+namespace AutoFixture.TUnit.Tests.Attributes.CompositeDataSourceAttributeTests;
+
+///
+/// End-to-end [CompositeDataSource] usage via the public attribute API.
+/// Partial child sources are expressed as BaseDataSourceAttribute derivatives —
+/// the supported extension point for custom data sources.
+///
+public class UsageScenarioTests
+{
+ [Test, LeadingAndTrailingComposite]
+ public async Task WhenCompositeZipsPartialRows_MergesByCollapse(string a, int b, string c)
+ {
+ await Assert.That<(string, int, string)[]>([
+ ("alpha", 1, "tail-a"),
+ ("beta", 2, "tail-b")
+ ]).Contains((a, b, c));
+ }
+
+ [Test, ArgumentsThenMemberComposite]
+ public async Task WhenCompositeCombinesAutoSources_RunsWithFirstSourceValues(
+ int id, string name, MyClass leftover)
+ {
+ await Assert.That(id).IsEqualTo(100);
+ await Assert.That(name).IsEqualTo("fixed-name");
+ await Assert.That(leftover).IsNotNull();
+ }
+
+ public class LeadingAndTrailingCompositeAttribute : CompositeDataSourceAttribute
+ {
+ public LeadingAndTrailingCompositeAttribute()
+ : base(
+ new FixedRowsAttribute(["alpha", 1], ["beta", 2]),
+ new FixedRowsAttribute(["x", 0, "tail-a"], ["y", 0, "tail-b"]))
+ {
+ }
+ }
+
+ public class ArgumentsThenMemberCompositeAttribute : CompositeDataSourceAttribute
+ {
+ public ArgumentsThenMemberCompositeAttribute()
+ : base(
+ new AutoArgumentsAttribute(100, "fixed-name"),
+ new AutoMemberDataSourceAttribute(nameof(SecondaryRows)))
+ {
+ }
+ }
+
+ public static IEnumerable SecondaryRows
+ {
+ get
+ {
+ yield return ["ignored-when-first-source-fills-all"];
+ yield return ["also-ignored"];
+ }
+ }
+
+ ///
+ /// Yields fixed rows without AutoFixture fill — same public extension model users get
+ /// by deriving .
+ ///
+ public class FixedRowsAttribute : BaseDataSourceAttribute
+ {
+ private readonly object?[][] rows;
+
+ public FixedRowsAttribute(params object?[][] rows)
+ {
+ this.rows = rows;
+ }
+
+#pragma warning disable CS1998
+ public override async IAsyncEnumerable>> GetData(
+ DataGeneratorMetadata dataGeneratorMetadata)
+ {
+ foreach (var row in this.rows)
+ {
+ var captured = row;
+ yield return () => Task.FromResult(captured);
+ }
+ }
+#pragma warning restore CS1998
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/CustomizeAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/CustomizeAttributeTests.cs
similarity index 65%
rename from tests/AutoFixture.TUnit.Tests/CustomizeAttributeTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/CustomizeAttributeTests.cs
index 8b7be44..f3b5ad9 100644
--- a/tests/AutoFixture.TUnit.Tests/CustomizeAttributeTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/CustomizeAttributeTests.cs
@@ -1,11 +1,11 @@
-using AutoFixture.TUnit.Tests.TestTypes;
+using AutoFixture.TUnit.Tests.TestTypes;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.Customizations;
public class CustomizeAttributeTest
{
[Test]
- public async Task TestableSutIsSut()
+ public async Task Constructor_WhenCreated_IsCustomizeAttribute()
{
// Arrange && Act
var sut = new DelegatingCustomizeAttribute();
@@ -15,7 +15,7 @@ public async Task TestableSutIsSut()
}
[Test]
- public async Task SutIsAttribute()
+ public async Task Constructor_WhenCreated_IsAttribute()
{
// Arrange && Act
var sut = new DelegatingCustomizeAttribute();
@@ -25,7 +25,7 @@ public async Task SutIsAttribute()
}
[Test]
- public async Task SutImplementsIParameterCustomizationSource()
+ public async Task Constructor_WhenCreated_ImplementsIParameterCustomizationSource()
{
// Arrange && Act
var sut = new DelegatingCustomizeAttribute();
@@ -33,4 +33,4 @@ public async Task SutImplementsIParameterCustomizationSource()
// Assert
await Assert.That(sut).IsAssignableTo();
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/FavorArraysAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorArraysAttributeTests.cs
similarity index 72%
rename from tests/AutoFixture.TUnit.Tests/FavorArraysAttributeTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorArraysAttributeTests.cs
index 40ac0f7..ab3caf4 100644
--- a/tests/AutoFixture.TUnit.Tests/FavorArraysAttributeTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorArraysAttributeTests.cs
@@ -1,13 +1,12 @@
-using AutoFixture.Kernel;
+using AutoFixture.Kernel;
using TestTypeFoundation;
-using TUnit.Assertions.Extensions;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.Customizations;
public class FavorArraysAttributeTest
{
[Test]
- public async Task SutIsAttribute()
+ public async Task Constructor_WhenCreated_IsAttribute()
{
// Arrange
// Act
@@ -17,22 +16,22 @@ public async Task SutIsAttribute()
}
[Test]
- public async Task GetCustomizationFromNullParameterThrows()
+ public async Task GetCustomization_WhenParameterIsNull_Throws()
{
// Arrange
var sut = new FavorArraysAttribute();
// Act & assert
await Assert.That(() =>
- sut.GetCustomization(null!)).ThrowsExactly();
+ sut.GetCustomization(null)).ThrowsExactly();
}
[Test]
- public async Task GetCustomizationReturnsCorrectResult()
+ public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult()
{
// Arrange
var sut = new FavorArraysAttribute();
var parameter = typeof(TypeWithOverloadedMembers)
- .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])!
+ .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])
.GetParameters().Single();
// Act
var result = sut.GetCustomization(parameter);
@@ -42,4 +41,4 @@ public async Task GetCustomizationReturnsCorrectResult()
await Assert.That(invoker.TargetType).IsEqualTo(parameter.ParameterType);
await Assert.That(invoker.Query).IsAssignableTo();
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/FavorEnumerablesAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorEnumerablesAttributeTests.cs
similarity index 72%
rename from tests/AutoFixture.TUnit.Tests/FavorEnumerablesAttributeTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorEnumerablesAttributeTests.cs
index 7c93ac7..55c7b58 100644
--- a/tests/AutoFixture.TUnit.Tests/FavorEnumerablesAttributeTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorEnumerablesAttributeTests.cs
@@ -1,13 +1,12 @@
-using AutoFixture.Kernel;
+using AutoFixture.Kernel;
using TestTypeFoundation;
-using TUnit.Assertions.Extensions;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.Customizations;
public class FavorEnumerablesAttributeTest
{
[Test]
- public async Task SutIsAttribute()
+ public async Task Constructor_WhenCreated_IsAttribute()
{
// Arrange
// Act
@@ -17,22 +16,22 @@ public async Task SutIsAttribute()
}
[Test]
- public async Task GetCustomizationFromNullParameterThrows()
+ public async Task GetCustomization_WhenParameterIsNull_Throws()
{
// Arrange
var sut = new FavorEnumerablesAttribute();
// Act & assert
await Assert.That(() =>
- sut.GetCustomization(null!)).ThrowsExactly();
+ sut.GetCustomization(null)).ThrowsExactly();
}
[Test]
- public async Task GetCustomizationReturnsCorrectResult()
+ public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult()
{
// Arrange
var sut = new FavorEnumerablesAttribute();
var parameter = typeof(TypeWithOverloadedMembers)
- .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])!
+ .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])
.GetParameters().Single();
// Act
var result = sut.GetCustomization(parameter);
@@ -42,4 +41,4 @@ public async Task GetCustomizationReturnsCorrectResult()
await Assert.That(invoker.TargetType).IsEqualTo(parameter.ParameterType);
await Assert.That(invoker.Query).IsAssignableTo();
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/FavorListsAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorListsAttributeTests.cs
similarity index 73%
rename from tests/AutoFixture.TUnit.Tests/FavorListsAttributeTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorListsAttributeTests.cs
index a8a5632..20bddd8 100644
--- a/tests/AutoFixture.TUnit.Tests/FavorListsAttributeTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FavorListsAttributeTests.cs
@@ -1,13 +1,12 @@
-using AutoFixture.Kernel;
+using AutoFixture.Kernel;
using TestTypeFoundation;
-using TUnit.Assertions.Extensions;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.Customizations;
public class FavorListsAttributeTest
{
[Test]
- public async Task SutIsAttribute()
+ public async Task Constructor_WhenCreated_IsAttribute()
{
// Arrange
// Act
@@ -17,22 +16,22 @@ public async Task SutIsAttribute()
}
[Test]
- public async Task GetCustomizationFromNullParameterThrows()
+ public async Task GetCustomization_WhenParameterIsNull_Throws()
{
// Arrange
var sut = new FavorListsAttribute();
// Act & assert
- await Assert.That(() => sut.GetCustomization(null!))
+ await Assert.That(() => sut.GetCustomization(null))
.ThrowsExactly();
}
[Test]
- public async Task GetCustomizationReturnsCorrectResult()
+ public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult()
{
// Arrange
var sut = new FavorListsAttribute();
var parameter = typeof(TypeWithOverloadedMembers)
- .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])!
+ .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])
.GetParameters().Single();
// Act
var result = sut.GetCustomization(parameter);
@@ -42,4 +41,4 @@ public async Task GetCustomizationReturnsCorrectResult()
await Assert.That(invoker.TargetType).IsEqualTo(parameter.ParameterType);
await Assert.That(invoker.Query).IsAssignableTo();
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/FrozenAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FrozenAttributeTests.cs
similarity index 60%
rename from tests/AutoFixture.TUnit.Tests/FrozenAttributeTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FrozenAttributeTests.cs
index ec37c16..48981e0 100644
--- a/tests/AutoFixture.TUnit.Tests/FrozenAttributeTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/FrozenAttributeTests.cs
@@ -1,11 +1,9 @@
-using TUnit.Assertions.Extensions;
-
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.Customizations;
public class FrozenAttributeTest
{
[Test]
- public async Task SutIsAttribute()
+ public async Task Constructor_WhenCreated_IsAttribute()
{
// Arrange
// Act
@@ -15,12 +13,12 @@ public async Task SutIsAttribute()
}
[Test]
- public async Task GetCustomizationFromNullParameterThrows()
+ public async Task GetCustomization_WhenParameterIsNull_Throws()
{
// Arrange
var sut = new FrozenAttribute();
// Act & assert
- await Assert.That(() => sut.GetCustomization(null!))
+ await Assert.That(() => sut.GetCustomization(null))
.ThrowsExactly();
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/GreedyAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/GreedyAttributeTests.cs
similarity index 73%
rename from tests/AutoFixture.TUnit.Tests/GreedyAttributeTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/GreedyAttributeTests.cs
index 8afe8b7..6f456d2 100644
--- a/tests/AutoFixture.TUnit.Tests/GreedyAttributeTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/GreedyAttributeTests.cs
@@ -1,16 +1,15 @@
-using AutoFixture.Kernel;
+using AutoFixture.Kernel;
using TestTypeFoundation;
-using TUnit.Assertions.Extensions;
#if NETCOREAPP1_1
using System.Reflection;
#endif
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.Customizations;
public class GreedyAttributeTest
{
[Test]
- public async Task SutIsAttribute()
+ public async Task Constructor_WhenCreated_IsAttribute()
{
// Arrange
// Act
@@ -20,22 +19,22 @@ public async Task SutIsAttribute()
}
[Test]
- public async Task GetCustomizationFromNullParameterThrows()
+ public async Task GetCustomization_WhenParameterIsNull_Throws()
{
// Arrange
var sut = new GreedyAttribute();
// Act & assert
- await Assert.That(() => sut.GetCustomization(null!))
+ await Assert.That(() => sut.GetCustomization(null))
.ThrowsExactly();
}
[Test]
- public async Task GetCustomizationReturnsCorrectResult()
+ public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult()
{
// Arrange
var sut = new GreedyAttribute();
var parameter = typeof(TypeWithOverloadedMembers)
- .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])!
+ .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])
.GetParameters().Single();
// Act
var result = sut.GetCustomization(parameter);
@@ -45,4 +44,4 @@ public async Task GetCustomizationReturnsCorrectResult()
await Assert.That(invoker.TargetType).IsEqualTo(parameter.ParameterType);
await Assert.That(invoker.Query).IsAssignableTo();
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/ModestAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ModestAttributeTests.cs
similarity index 72%
rename from tests/AutoFixture.TUnit.Tests/ModestAttributeTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ModestAttributeTests.cs
index 796c6a4..ee8d8d8 100644
--- a/tests/AutoFixture.TUnit.Tests/ModestAttributeTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ModestAttributeTests.cs
@@ -1,13 +1,12 @@
-using AutoFixture.Kernel;
+using AutoFixture.Kernel;
using TestTypeFoundation;
-using TUnit.Assertions.Extensions;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.Customizations;
public class ModestAttributeTest
{
[Test]
- public async Task SutIsAttribute()
+ public async Task Constructor_WhenCreated_IsAttribute()
{
// Arrange & Act
var sut = new ModestAttribute();
@@ -16,22 +15,22 @@ public async Task SutIsAttribute()
}
[Test]
- public async Task GetCustomizationFromNullParameterThrows()
+ public async Task GetCustomization_WhenParameterIsNull_Throws()
{
// Arrange
var sut = new ModestAttribute();
// Act & assert
- await Assert.That(() => sut.GetCustomization(null!))
+ await Assert.That(() => sut.GetCustomization(null))
.ThrowsExactly();
}
[Test]
- public async Task GetCustomizationReturnsCorrectResult()
+ public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult()
{
// Arrange
var sut = new ModestAttribute();
var parameter = typeof(TypeWithOverloadedMembers)
- .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])!
+ .GetMethod(nameof(TypeWithOverloadedMembers.DoSomething), [typeof(object)])
.GetParameters().Single();
// Act
@@ -43,4 +42,4 @@ public async Task GetCustomizationReturnsCorrectResult()
await Assert.That(invoker.TargetType).IsEqualTo(parameter.ParameterType);
await Assert.That(invoker.Query).IsAssignableTo();
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/NoAutoPropertiesAttributeTest.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/NoAutoPropertiesAttributeTests.cs
similarity index 69%
rename from tests/AutoFixture.TUnit.Tests/NoAutoPropertiesAttributeTest.cs
rename to tests/AutoFixture.TUnit.Tests/Attributes/Customizations/NoAutoPropertiesAttributeTests.cs
index 024159d..f9b4ba5 100644
--- a/tests/AutoFixture.TUnit.Tests/NoAutoPropertiesAttributeTest.cs
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/NoAutoPropertiesAttributeTests.cs
@@ -1,12 +1,11 @@
-using TestTypeFoundation;
-using TUnit.Assertions.Extensions;
+using TestTypeFoundation;
-namespace AutoFixture.TUnit.Tests;
+namespace AutoFixture.TUnit.Tests.Attributes.Customizations;
public class NoAutoPropertiesAttributeTest
{
[Test]
- public async Task SutIsAttribute()
+ public async Task Constructor_WhenCreated_IsAttribute()
{
// Arrange
// Act
@@ -16,17 +15,17 @@ public async Task SutIsAttribute()
}
[Test]
- public async Task GetCustomizationFromNullParameterThrows()
+ public async Task GetCustomization_WhenParameterIsNull_Throws()
{
// Arrange
var sut = new NoAutoPropertiesAttribute();
// Act & assert
- await Assert.That(() => sut.GetCustomization(null!))
+ await Assert.That(() => sut.GetCustomization(null))
.ThrowsExactly();
}
[Test]
- public async Task GetCustomizationReturnsTheCorrectResult()
+ public async Task GetCustomization_WhenParameterProvided_ReturnsCorrectResult()
{
// Arrange
var sut = new NoAutoPropertiesAttribute();
@@ -38,4 +37,4 @@ public async Task GetCustomizationReturnsTheCorrectResult()
// Assert
await Assert.That(result).IsAssignableTo();
}
-}
\ No newline at end of file
+}
diff --git a/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ScenarioTests.cs b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ScenarioTests.cs
new file mode 100644
index 0000000..36600ea
--- /dev/null
+++ b/tests/AutoFixture.TUnit.Tests/Attributes/Customizations/ScenarioTests.cs
@@ -0,0 +1,337 @@
+using System.ComponentModel.DataAnnotations;
+using AutoFixture.TUnit.Tests.TestTypes;
+using TestTypeFoundation;
+using ConcreteType = TestTypeFoundation.ConcreteType;
+
+namespace AutoFixture.TUnit.Tests.Attributes.Customizations;
+
+///
+/// End-to-end customization usage with [AutoDataSource], moved from the old Scenarios bucket.
+///
+public class ScenarioTests
+{
+ [Test, AutoDataSource]
+ public async Task WhenFirstParameterFrozen_SecondMatchesFirst([Frozen] Guid g1, Guid g2)
+ {
+ await Assert.That(g2).IsEqualTo(g1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenSecondParameterFrozen_OnlySubsequentMatch(Guid g1, [Frozen] Guid g2, Guid g3)
+ {
+ await Assert.That(g2).IsNotEqualTo(g1);
+ await Assert.That(g3).IsNotEqualTo(g1);
+
+ await Assert.That(g3).IsEqualTo(g2);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenModestApplied_UsesModestConstructor([Modest] MultiUnorderedConstructorType p)
+ {
+ await Assert.That(string.IsNullOrEmpty(p.Text)).IsTrue();
+ await Assert.That(p.Number).IsEqualTo(0);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenGreedyApplied_UsesGreedyConstructor([Greedy] MultiUnorderedConstructorType p)
+ {
+ await Assert.That(string.IsNullOrEmpty(p.Text)).IsFalse();
+ await Assert.That(p.Number).IsNotEqualTo(0);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenAndGreedyOnSameParameter_BothApply(
+ [Frozen][Greedy] MultiUnorderedConstructorType p1, MultiUnorderedConstructorType p2)
+ {
+ await Assert.That(p1).IsNotNull();
+ await Assert.That(string.IsNullOrEmpty(p2.Text)).IsFalse();
+ await Assert.That(p2.Number).IsNotEqualTo(0);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenGreedyAndFrozenOnSameParameter_BothApply(
+ [Greedy][Frozen] MultiUnorderedConstructorType p1, MultiUnorderedConstructorType p2)
+ {
+ await Assert.That(p1).IsNotNull();
+ await Assert.That(string.IsNullOrEmpty(p2.Text)).IsFalse();
+ await Assert.That(p2.Number).IsNotEqualTo(0);
+ await Assert.That(p2).IsSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenNoAutoPropertiesApplied_LeavesPropertiesUnset(
+ [NoAutoProperties] PropertyHolder ph1,
+ [NoAutoProperties] PropertyHolder ph2,
+ [NoAutoProperties] PropertyHolder ph3)
+ {
+ await Assert.That(ph1.Property).IsEqualTo(default(object));
+ await Assert.That(ph2.Property).IsEqualTo(default(string));
+ await Assert.That(ph3.Property).IsEqualTo(default(int));
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFavorArraysAndFrozen_InjectsArrayConstructorWithFrozenItems([Frozen] int[] numbers,
+ [FavorArrays] ItemContainer container)
+ {
+ await Assert.That(numbers.SequenceEqual(container.Items)).IsTrue();
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFavorEnumerablesApplied_UsesEnumerableConstructor(
+ [FavorEnumerables] CompositeTypeWithOverloadedConstructors numbers)
+ {
+ await Assert.That(numbers.Items).IsAssignableTo>();
+ await Assert.That(numbers.Items).IsNotTypeOf>();
+ await Assert.That(numbers.Items).IsNotTypeOf();
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFavorListsApplied_UsesListConstructor(
+ [FavorLists] CompositeTypeWithOverloadedConstructors strings)
+ {
+ await Assert.That(strings.Items).IsAssignableTo>();
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFirstParameterFrozen_AssignsSameInstanceToSecond([Frozen] string p1,
+ string p2)
+ {
+ await Assert.That(p2).IsEqualTo(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByExactType_AssignsSameInstanceToSecond(
+ [Frozen(Matching.ExactType)] ConcreteType p1,
+ ConcreteType p2)
+ {
+ await Assert.That(p2).IsEqualTo(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByExactType_DoesNotAssignToDifferentType(
+ [Frozen(Matching.ExactType)] ConcreteType p1,
+ object p2)
+ {
+ await Assert.That(p2).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByDirectBaseType_AssignsSameInstanceToSecond(
+ [Frozen(Matching.DirectBaseType)] ConcreteType p1,
+ AbstractType p2)
+ {
+ await Assert.That(p2).IsSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByDirectBaseType_DoesNotAssignToIndirectBaseType(
+ [Frozen(Matching.DirectBaseType)] ConcreteType p1,
+ object p2)
+ {
+ await Assert.That(p2).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByDirectBaseType_DoesNotAssignToSameType(
+ [Frozen(Matching.DirectBaseType)] ConcreteType p1,
+ ConcreteType p2)
+ {
+ await Assert.That(p2).IsNotEqualTo(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByExactOrDirectBaseType_AssignsSameInstanceToSameType(
+ [Frozen(Matching.ExactType | Matching.DirectBaseType)]
+ ConcreteType p1,
+ ConcreteType p2)
+ {
+ await Assert.That(p2).IsEqualTo(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByInterface_AssignsSameInstanceToSecond(
+ [Frozen(Matching.ImplementedInterfaces)]
+ NoopInterfaceImplementer p1,
+ IInterface p2)
+ {
+ await Assert.That(p2).IsSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByInterface_DoesNotAssignToNonInterfaceType(
+ [Frozen(Matching.ImplementedInterfaces)]
+ NoopInterfaceImplementer p1,
+ object p2)
+ {
+ await Assert.That(p2).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByInterface_DoesNotAssignToSameType(
+ [Frozen(Matching.ImplementedInterfaces)]
+ NoopInterfaceImplementer p1,
+ NoopInterfaceImplementer p2)
+ {
+ await Assert.That(p2).IsNotEqualTo(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByDirectOrInterface_AssignsSameInstanceToSameType(
+ [Frozen(Matching.ExactType | Matching.ImplementedInterfaces)]
+ NoopInterfaceImplementer p1,
+ NoopInterfaceImplementer p2)
+ {
+ await Assert.That(p2).IsEqualTo(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByParameterSameName_AssignsSameInstanceToSecond(
+ [Frozen(Matching.ParameterName)] string parameter,
+ SingleParameterType p2)
+ {
+ await Assert.That(p2.Parameter).IsSameReferenceAs(parameter);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByParameterDifferentName_DoesNotAssignToSecond(
+ [Frozen(Matching.ParameterName)] string p1,
+ SingleParameterType p2)
+ {
+ await Assert.That(p2.Parameter).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByParameterDifferentName_DoesNotAssignToSameType(
+ [Frozen(Matching.ParameterName)] string p1,
+ SingleParameterType p2)
+ {
+ await Assert.That(p2.Parameter).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByPropertySameName_AssignsSameInstanceToSecond(
+ [Frozen(Matching.PropertyName)] string property,
+ PropertyHolder p2)
+ {
+ await Assert.That(p2.Property).IsSameReferenceAs(property);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByPropertyDifferentName_DoesNotAssignToSecond(
+ [Frozen(Matching.PropertyName)] string p1,
+ PropertyHolder p2)
+ {
+ await Assert.That(p2.Property).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByPropertyDifferentName_DoesNotAssignToSameType(
+ [Frozen(Matching.PropertyName)] string p1,
+ PropertyHolder p2)
+ {
+ await Assert.That(p2.Property).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByFieldSameName_AssignsSameInstanceToSecond(
+ [Frozen(Matching.FieldName)] string field,
+ FieldHolder p2)
+ {
+ await Assert.That(p2.Field).IsSameReferenceAs(field);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByFieldDifferentName_DoesNotAssignToSecond(
+ [Frozen(Matching.FieldName)] string p1,
+ FieldHolder p2)
+ {
+ await Assert.That(p2.Field).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByFieldDifferentName_DoesNotAssignToSameType(
+ [Frozen(Matching.FieldName)] string p1,
+ FieldHolder p2)
+ {
+ await Assert.That(p2.Field).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByMemberSameName_AssignsSameInstanceToMatchingParameter(
+ [Frozen(Matching.MemberName)] string parameter,
+ SingleParameterType p2)
+ {
+ await Assert.That(p2.Parameter).IsSameReferenceAs(parameter);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToParameter(
+ [Frozen(Matching.MemberName)] string p1,
+ SingleParameterType p2)
+ {
+ await Assert.That(p2.Parameter).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToParameterOfSameType(
+ [Frozen(Matching.MemberName)] string p1,
+ SingleParameterType p2)
+ {
+ await Assert.That(p2.Parameter).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByMemberSameName_AssignsSameInstanceToMatchingProperty(
+ [Frozen(Matching.MemberName)] string property,
+ PropertyHolder p2)
+ {
+ await Assert.That(p2.Property).IsSameReferenceAs(property);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToProperty(
+ [Frozen(Matching.MemberName)] string p1,
+ PropertyHolder p2)
+ {
+ await Assert.That(p2.Property).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToPropertyOfSameType(
+ [Frozen(Matching.MemberName)] string p1,
+ PropertyHolder p2)
+ {
+ await Assert.That(p2.Property).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByMemberSameName_AssignsSameInstanceToMatchingField(
+ [Frozen(Matching.MemberName)] string field,
+ FieldHolder p2)
+ {
+ await Assert.That(p2.Field).IsSameReferenceAs(field);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToField(
+ [Frozen(Matching.MemberName)] string p1,
+ FieldHolder p2)
+ {
+ await Assert.That(p2.Field).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenByMemberDifferentName_DoesNotAssignToFieldOfSameType(
+ [Frozen(Matching.MemberName)] string p1,
+ FieldHolder p2)
+ {
+ await Assert.That(p2.Field).IsNotSameReferenceAs(p1);
+ }
+
+ [Test, AutoDataSource]
+ public async Task WhenFrozenWithStringLengthConstraint_CreatesConstrainedSpecimen(
+ [Frozen, StringLength(3)] string p)
+ {
+ await Assert.That(p.Length == 3).IsTrue();
+ }
+}
diff --git a/tests/AutoFixture.TUnit.Tests/AutoFixture.TUnit.Tests.csproj b/tests/AutoFixture.TUnit.Tests/AutoFixture.TUnit.Tests.csproj
index a9bc845..7579098 100644
--- a/tests/AutoFixture.TUnit.Tests/AutoFixture.TUnit.Tests.csproj
+++ b/tests/AutoFixture.TUnit.Tests/AutoFixture.TUnit.Tests.csproj
@@ -8,22 +8,17 @@
disable
-
-