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 @@ [![License](https://img.shields.io/badge/license-MIT-green)](https://raw.githubusercontent.com/AutoFixture/AutoFixture.TUnit/master/LICENCE.txt) [![NuGet version](https://img.shields.io/nuget/v/AutoFixture.TUnit?logo=nuget)](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). +

+ + + + AutoFixture + + +

+ ## 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` / `IEnumerable` | Each array is one multi-column row | +| `IEnumerable` (for example `IEnumerable`) | Each item is one single-cell row | +| `IEnumerable<(T1, T2, ...)>` | Each tuple expands into columns | +| `(T1, T2, ...)` | One row with expanded columns | +| Scalar (`string`, `int`, custom type, …) | One single-cell row (`string` is not enumerated as chars) | +| `null` | One row with a single `null` cell | +| `Task` / nested `Task`s | Awaited, then the result is interpreted as above | +| `IAsyncEnumerable` | Same row rules as the sync sequences above | +| Empty sequence | No rows | + +```csharp +using System.Collections; +using System.Collections.Generic; +using TUnit; +using TUnit.Assertions; +using AutoFixture.TUnit; + +public class CalculatorTests +{ + // Multi-column rows + public static IEnumerable ObjectArrayRows => + [ + [2, 3], + [10, -4] + ]; + + // Single-cell rows from a typed sequence + public static IEnumerable StringRows => ["left", "right"]; + + // Tuples expand to columns + public static IEnumerable<(int Left, int Right)> TupleRows => + [ + (2, 3), + (10, -4) + ]; + + // One tuple => one row + public static (int Left, int Right) SingleTupleRow => (5, 8); + + // Scalar => one single-cell row + public static string StringScalar => "seed"; + + // Async method (for example loading rows from a file or database) + public static async Task> TaskObjectArrayRows() + { + await Task.Yield(); // stand-in for real I/O + return [[1, 1], [7, 8]]; + } + + // Streaming rows as they become available + public static async IAsyncEnumerable<(int Left, int Right)> AsyncTupleRows() + { + yield return (2, 3); + await Task.Yield(); + yield return (10, -4); + } + + [Test, AutoMemberDataSource(nameof(ObjectArrayRows))] + public async Task Add_ObjectArrayRows_ReturnsExpectedTotal( + int a, int b, Calculator calculator) + { + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); + } + + [Test, AutoMemberDataSource(nameof(TupleRows))] + public async Task Add_TupleRows_ReturnsExpectedTotal( + int a, int b, Calculator calculator) + { + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); + } + + [Test, AutoClassDataSource(typeof(KnownSumRows))] + public async Task Add_ClassData_ReturnsExpectedTotal( + int a, int b, Calculator calculator) + { + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); + } +} + +public class KnownSumRows : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return [1, 1]; + yield return [7, 8]; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} +``` + +Class data providers can return the same shapes (for example `IEnumerable`, `IEnumerable`, or `IEnumerable<(string, int)>`). + +Generic attribute forms (C# 11+) avoid `typeof(...)` for the provider or member host type, and strongly type a single inline argument: + +```csharp +[Test, AutoMemberDataSource(nameof(ObjectArrayRows))] +public async Task Add_GenericMember_ReturnsExpectedTotal(int a, int b, Calculator calculator) +{ + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); +} + +[Test, AutoClassDataSource] +public async Task Add_GenericClassData_ReturnsExpectedTotal(int a, int b, Calculator calculator) +{ + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); +} + +[Test, AutoArguments(2)] +public async Task Add_GenericArguments_FillsRemaining(int a, int b, Calculator calculator) +{ + await Assert.That(a).IsEqualTo(2); + await Assert.That(calculator.Add(a, b)).IsEqualTo(a + b); +} + +// Prefer AutoArguments when the value is an array: non-generic +// [AutoArguments(new object[] { 1, 2 })] expands into separate cells because of params object?[]. +[Test, AutoArguments(new int[] { 1, 2 })] +public async Task Add_GenericArrayArgument_KeepsArrayAsOneParameter(int[] values, Calculator calculator) +{ + await Assert.That(values).IsEquivalentTo(new[] { 1, 2 }); + await Assert.That(calculator).IsNotNull(); +} +``` + ### Freezing Dependencies AutoFixture's `[Frozen]` attribute can be used to ensure that the same instance of a dependency is injected into multiple parameters. @@ -107,6 +253,7 @@ public class Consumer You can freeze the Dependency so that all requests for it within the test will return the same instance: ```csharp +using TUnit; using TUnit.Assertions; using AutoFixture.TUnit; @@ -127,14 +274,14 @@ public class ConsumerTests ### Data Source Attributes - **`[AutoDataSource]`** - Automatically generates test data for all parameters -- **`[AutoArguments]`** - Combines inline values with auto-generated data -- **`[AutoMemberDataSource]`** - Uses static members (properties, fields, methods) as data sources -- **`[AutoClassDataSource]`** - Uses classes implementing `IEnumerable` as data sources +- **`[AutoArguments]`** / **`[AutoArguments]`** - Combines inline values with auto-generated data (`T` is a single strongly typed inline value; C# 11+) +- **`[AutoMemberDataSource]`** / **`[AutoMemberDataSource]`** - Uses static members (properties, fields, methods) as data sources; the generic form takes the member-declaring type as `T` (C# 11+) +- **`[AutoClassDataSource]`** / **`[AutoClassDataSource]`** - Uses a provider type as a data source; the generic form takes the provider type as `T` (C# 11+). This is not the same as TUnit's `[ClassDataSource]`, which injects an instance of `T` - **`[CompositeDataSource]`** - Composes multiple data source attributes together ### Parameter Customization Attributes -- **`[Frozen]`** - Freezes a parameter value so the same instance is reused (supports various matching criteria) +- **`[Frozen]`** - Freezes a parameter value so the same instance is reused (supports various matching criteria via `Matching`) - **`[Greedy]`** - Uses the constructor with the most parameters - **`[Modest]`** - Uses the constructor with the fewest parameters - **`[NoAutoProperties]`** - Prevents auto-population of properties @@ -142,14 +289,15 @@ public class ConsumerTests - **`[FavorEnumerables]`** - Prefers constructors that take `IEnumerable` parameters - **`[FavorLists]`** - Prefers constructors that take `IList` parameters -All customization attributes can be combined and support custom fixture factories for advanced scenarios. +Customization attributes can be combined on parameters. +Data source attributes also support custom fixture factories through derived attributes for advanced scenarios. ## Contributing -Contributions are welcome! -If you would like to contribute, please review our contributing guidelines and open an issue or pull request. +Contributions are welcome! +If you would like to contribute, please review our [contributing guidelines](CONTRIBUTING.md) and open an issue or pull request. ## License -AutoFixture is Open Source software and is released under the [MIT license](LICENCE.txt). -The license allows the use of AutoFixture libraries in free and commercial applications and libraries without restrictions. +AutoFixture.TUnit is Open Source software and is released under the [MIT license](LICENCE.txt). +The license allows the use of AutoFixture.TUnit libraries in free and commercial applications and libraries without restrictions. diff --git a/assets/icon-square-color.svg b/assets/icon-square-color.svg new file mode 100644 index 0000000..583e7c4 --- /dev/null +++ b/assets/icon-square-color.svg @@ -0,0 +1,7 @@ + + AutoFixture + + + + + diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000..e2d290b Binary files /dev/null and b/assets/icon.png differ diff --git a/assets/lockup-dark.svg b/assets/lockup-dark.svg new file mode 100644 index 0000000..6ab3875 --- /dev/null +++ b/assets/lockup-dark.svg @@ -0,0 +1,18 @@ + + AutoFixture + + + + + + AutoFixture + + diff --git a/assets/lockup-light.svg b/assets/lockup-light.svg new file mode 100644 index 0000000..5dc350b --- /dev/null +++ b/assets/lockup-light.svg @@ -0,0 +1,18 @@ + + AutoFixture + + + + + + AutoFixture + + diff --git a/assets/readme.md b/assets/readme.md new file mode 100644 index 0000000..01eb910 --- /dev/null +++ b/assets/readme.md @@ -0,0 +1,105 @@ +# AutoFixture.TUnit + +AutoFixture.TUnit integrates [AutoFixture](https://github.com/AutoFixture/AutoFixture) with [TUnit](https://github.com/thomhurst/TUnit). Use data-source attributes to generate arguments declaratively so tests stay focused on behavior, not setup. + +Full documentation, data-shape reference, and contributing guide: [github.com/AutoFixture/AutoFixture.TUnit](https://github.com/AutoFixture/AutoFixture.TUnit). + +## Install + +```bash +dotnet add package AutoFixture.TUnit +``` + +## Quick start + +`[AutoDataSource]` fills every parameter with AutoFixture-generated values: + +```csharp +using TUnit; +using TUnit.Assertions; +using AutoFixture.TUnit; + +public class Calculator +{ + public int Add(int a, int b) => a + b; +} + +public class CalculatorTests +{ + [Test, AutoDataSource] + public async Task Add_SimpleValues_ReturnsCorrectResult( + Calculator calculator, int a, int b) + { + int result = calculator.Add(a, b); + + await Assert.That(result).IsEqualTo(a + b); + } +} +``` + +## Inline values + +`[AutoArguments]` supplies some arguments; AutoFixture fills the rest: + +```csharp +[Test] +[AutoArguments(5, 8)] +public async Task Add_SpecificValues_ReturnsCorrectResult( + int a, int b, Calculator calculator) +{ + await Assert.That(calculator.Add(a, b)).IsEqualTo(13); +} +``` + +Prefer `[AutoArguments]` (C# 11+) when you need a strongly typed single value, especially arrays that must stay one parameter: + +```csharp +[Test, AutoArguments(new int[] { 1, 2 })] +public async Task Add_GenericArrayArgument_KeepsArrayAsOneParameter( + int[] values, Calculator calculator) +{ + await Assert.That(values).IsEquivalentTo([1, 2]); + await Assert.That(calculator).IsNotNull(); +} +``` + +## Freeze shared instances + +Use `[Frozen]` when several parameters should receive the same instance: + +```csharp +public class Dependency { } + +public class Consumer +{ + public Dependency Dependency { get; } + public Consumer(Dependency dependency) => Dependency = dependency; +} + +public class ConsumerTests +{ + [Test, AutoDataSource] + public async Task Consumer_UsesSameDependency( + [Frozen] Dependency dependency, Consumer consumer) + { + await Assert.That(consumer.Dependency).IsSameReferenceAs(dependency); + } +} +``` + +## Main attributes + +| Attribute | Role | +| --- | --- | +| `[AutoDataSource]` | Generate all parameters | +| `[AutoArguments]` / `[AutoArguments]` | Mix inline values with generated data | +| `[AutoMemberDataSource]` / `[AutoMemberDataSource]` | Rows from a static member; remaining parameters are generated | +| `[AutoClassDataSource]` / `[AutoClassDataSource]` | Rows from a provider type; remaining parameters are generated | +| `[CompositeDataSource]` | Compose multiple data-source attributes | +| `[Frozen]`, `[Greedy]`, `[Modest]`, `[NoAutoProperties]`, `[FavorArrays]`, `[FavorEnumerables]`, `[FavorLists]` | Parameter / construction customizations | + +Member and class sources accept the same result shapes as TUnit method data sources (`object[]` rows, tuples, scalars, `Task`, `IAsyncEnumerable`, and more). See the [repository README](https://github.com/AutoFixture/AutoFixture.TUnit#member-and-class-data-sources) for the full shape table and examples. + +## License + +AutoFixture.TUnit is released under the [MIT license](https://github.com/AutoFixture/AutoFixture.TUnit/blob/master/LICENCE.txt). diff --git a/build/Build.cs b/build/Build.cs index e209985..a6e3de6 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Nuke.Common; @@ -45,7 +46,7 @@ class Build : NukeBuild [Solution("AutoFixture.TUnit.sln")] readonly Solution Solution; [GitRepository] readonly GitRepository GitRepository; - [GitVersion] readonly GitVersion GitVersion; + [GitVersion(NoFetch = true)] readonly GitVersion GitVersion; [CI] readonly GitHubActions GitHubActions; [Parameter("GitHub auth token", Name = "github-token"), Secret] readonly string GitHubToken; @@ -62,7 +63,8 @@ class Build : NukeBuild IEnumerable TestProjects => Solution.GetAllProjects("*Tests"); IEnumerable Libraries => Solution.Projects.Except(TestProjects).Except(Excluded); - IEnumerable CSharpLibraries => Libraries.Where(x => x.Is(ProjectType.CSharpProject)); + IEnumerable CSharpLibraries => + Libraries.Where(x => x.Path.ToString().EndsWith(".csproj", StringComparison.OrdinalIgnoreCase)); IEnumerable Packages => PackagesDirectory.GlobFiles("*.nupkg"); bool IsContinuousIntegration => IsServerBuild || CI; @@ -129,9 +131,10 @@ class Build : NukeBuild .SetResultsDirectory(TestResultsDirectory) .SetNoBuild(FinishedTargets.Contains(Compile)) .When(_ => InvokedTargets.Contains(Cover), _ => _ + // Do not pin a shared --coverage-output path: multi-TFM hosts race on one + // file and the empty net48 report can wipe populated net* coverage. .AddProcessAdditionalArguments("--") .AddProcessAdditionalArguments("--coverage") - .AddProcessAdditionalArguments("--coverage-output", TestResultsDirectory / "coverage.cobertura.xml") .AddProcessAdditionalArguments("--coverage-output-format", "cobertura"))); var testArchive = TestResultsDirectory / "TestResults.zip"; @@ -149,7 +152,7 @@ class Build : NukeBuild ReportGenerator(_ => _ .SetFramework("net8.0") .SetAssemblyFilters("-TestTypeFoundation*") - .SetReports(TestResultsDirectory / "**" / "coverage.cobertura.xml") + .SetReports(TestResultsDirectory / "**" / "*.cobertura.xml") .SetTargetDirectory(ReportsDirectory) .SetReportTypes("lcov", ReportTypes.HtmlInline)); diff --git a/build/_build.csproj b/build/_build.csproj index f422706..36fc409 100644 --- a/build/_build.csproj +++ b/build/_build.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 CS0649;CS0169 .. @@ -16,8 +16,10 @@ + - + + diff --git a/src/AutoFixture.TUnit/AutoArgumentsAttribute.cs b/src/AutoFixture.TUnit/AutoArgumentsAttribute.cs index 9d41b0b..6093d7e 100644 --- a/src/AutoFixture.TUnit/AutoArgumentsAttribute.cs +++ b/src/AutoFixture.TUnit/AutoArgumentsAttribute.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit; @@ -48,4 +48,4 @@ protected AutoArgumentsAttribute(Func fixtureFactory, params object?[] return new AutoDataSource(this.FixtureFactory, new InlineDataSource(this.Values)) .GetDataRowsAsync(dataGeneratorMetadata); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/AutoArgumentsAttribute{T}.cs b/src/AutoFixture.TUnit/AutoArgumentsAttribute{T}.cs new file mode 100644 index 0000000..1a06bf8 --- /dev/null +++ b/src/AutoFixture.TUnit/AutoArgumentsAttribute{T}.cs @@ -0,0 +1,36 @@ +using System.Diagnostics.CodeAnalysis; + +namespace AutoFixture.TUnit; + +/// +/// Generic form of that supplies a single strongly typed inline value, +/// with remaining parameters filled by AutoFixture. +/// +/// The type of the inline value. +/// +/// Requires C# 11 or later to use the [AutoArguments<T>] attribute syntax. +/// +[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", + Justification = "This attribute is the root of a potential attribute hierarchy.")] +public class AutoArgumentsAttribute : AutoArgumentsAttribute +{ + /// + /// Initializes a new instance of the class. + /// + /// The typed value to pass as the first theory argument. + public AutoArgumentsAttribute(T value) + : base([value]) + { + } + + /// + /// Initializes a new instance of the class + /// with a custom fixture factory. + /// + /// The fixture factory. + /// The typed value to pass as the first theory argument. + protected AutoArgumentsAttribute(Func fixtureFactory, T value) + : base(fixtureFactory, [value]) + { + } +} diff --git a/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs index ff575a7..ad7c3ed 100644 --- a/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs +++ b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute.cs @@ -1,11 +1,12 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit; /// /// Provides a data source for a data theory, with the data coming from a class -/// which must implement IEnumerable<object?[]>, +/// that yields test cases in any shape supported by TUnit MethodDataSource +/// (for example IEnumerable<object?[]>, IEnumerable<T>, or tuples), /// combined with auto-generated data specimens generated by AutoFixture. /// [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", @@ -51,9 +52,9 @@ public AutoClassDataSourceAttribute(Type sourceType, params object?[] parameters /// { /// public IEnumerator<object?[]> GetEnumerator() /// { - /// yield return new object?[] { 0, new int[0] }; - /// yield return new object?[] { 4, new int[] { 1, 2, 1} }; - /// yield return new object?[] { 23, new int [] { 0, 13, 15, -5 } }; + /// yield return [0, []]; + /// yield return [4, [1, 2, 1]]; + /// yield return [23, [0, 13, 15, -5]]; /// } /// /// IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); @@ -90,4 +91,4 @@ protected AutoClassDataSourceAttribute(Func fixtureFactory, Type sourc return source.GetDataRowsAsync(dataGeneratorMetadata); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs new file mode 100644 index 0000000..7e968b4 --- /dev/null +++ b/src/AutoFixture.TUnit/AutoClassDataSourceAttribute{T}.cs @@ -0,0 +1,41 @@ +using System.Diagnostics.CodeAnalysis; + +namespace AutoFixture.TUnit; + +/// +/// Generic form of that takes the data provider type +/// as a type argument instead of . +/// +/// +/// The data provider type that yields test rows (for example an +/// of object arrays). +/// This is not the same as TUnit's ClassDataSource<T>, which injects an instance of +/// as a dependency. +/// +/// +/// Requires C# 11 or later to use the [AutoClassDataSource<T>] attribute syntax. +/// +[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", + Justification = "This attribute is the root of a potential attribute hierarchy.")] +public class AutoClassDataSourceAttribute : AutoClassDataSourceAttribute +{ + /// + /// Initializes a new instance of the class. + /// + /// The parameters passed to the data provider class constructor. + public AutoClassDataSourceAttribute(params object?[] parameters) + : base(typeof(T), parameters) + { + } + + /// + /// Initializes a new instance of the class + /// with a custom fixture factory. + /// + /// The fixture factory that provides missing data from . + /// The parameters passed to the data provider class constructor. + protected AutoClassDataSourceAttribute(Func fixtureFactory, params object?[] parameters) + : base(fixtureFactory, typeof(T), parameters) + { + } +} diff --git a/src/AutoFixture.TUnit/AutoDataSourceAttribute.cs b/src/AutoFixture.TUnit/AutoDataSourceAttribute.cs index a09281f..91d946d 100644 --- a/src/AutoFixture.TUnit/AutoDataSourceAttribute.cs +++ b/src/AutoFixture.TUnit/AutoDataSourceAttribute.cs @@ -1,11 +1,10 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit; /// -/// Provides auto-generated data specimens generated by AutoFixture as an extension to -/// xUnit.net's Theory attribute. +/// Provides auto-generated data specimens generated by AutoFixture as a TUnit data source. /// [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "This attribute is the root of a potential attribute hierarchy.")] @@ -48,4 +47,4 @@ protected AutoDataSourceAttribute(Func fixtureFactory) return source.GetDataRowsAsync(dataGeneratorMetadata); } -} \ No newline at end of file +} diff --git a/src/AutoFixture.TUnit/AutoFixture.TUnit.csproj b/src/AutoFixture.TUnit/AutoFixture.TUnit.csproj index c5515f8..48cce03 100644 --- a/src/AutoFixture.TUnit/AutoFixture.TUnit.csproj +++ b/src/AutoFixture.TUnit/AutoFixture.TUnit.csproj @@ -16,7 +16,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all
- + 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 - - - - win7-x86 - - - - - - - - - + + + AnyCPU + - + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/tests/AutoFixture.TUnit.Tests/DependencyConstraintsTests.cs b/tests/AutoFixture.TUnit.Tests/DependencyConstraintsTests.cs index df67e71..6f00142 100644 --- a/tests/AutoFixture.TUnit.Tests/DependencyConstraintsTests.cs +++ b/tests/AutoFixture.TUnit.Tests/DependencyConstraintsTests.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace AutoFixture.TUnit.Tests; @@ -15,7 +15,9 @@ public class DependencyConstraintsTests [Arguments("Unquote")] [Arguments("xunit")] [Arguments("xunit.extensions")] - public async Task AssemblyDoesNotReference(string assemblyName) + [Arguments("TUnit.Engine")] + [Arguments("TUnit.Assertions")] + public async Task WhenPackageNameGiven_DoesNotReferenceAssembly(string assemblyName) { // Arrange && Act var typeInfo = typeof(AutoDataSourceAttribute).GetTypeInfo(); @@ -36,7 +38,7 @@ await Assert.That(referencedAssemblies) [Arguments("Unquote")] [Arguments("xunit")] [Arguments("xunit.extensions")] - public async Task UnitTestsAssemblyDoesNotReference(string assemblyName) + public async Task WhenPackageNameGiven_UnitTestsAssemblyDoesNotReference(string assemblyName) { // Arrange && Act var typeInfo = this.GetType().GetTypeInfo(); @@ -46,4 +48,4 @@ public async Task UnitTestsAssemblyDoesNotReference(string assemblyName) await Assert.That(referencedAssemblies) .DoesNotContain(an => an.Name == assemblyName); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/ClassDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/ClassDataSourceTests.cs deleted file mode 100644 index b184f47..0000000 --- a/tests/AutoFixture.TUnit.Tests/Internal/ClassDataSourceTests.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System.Collections; -using AutoFixture.TUnit.Internal; -using AutoFixture.TUnit.Tests.TestTypes; -using TestTypeFoundation; -using TUnit.Assertions.Extensions; - -namespace AutoFixture.TUnit.Tests.Internal; - -public class ClassDataSourceTests -{ - [Test] - public async Task SutIsTestDataSource() - { - // Arrange & Act - var sut = new ClassDataSource(typeof(object)); - - // Assert - await Assert.That(sut).IsAssignableTo(); - } - - [Test] - public async Task ConstructorWithNullTypeThrows() - { - // Act & Assert - await Assert.That(() => _ = new ClassDataSource(null!)).ThrowsExactly(); - } - - [Test] - public async Task ConstructorWithNullParametersThrows() - { - // Act & Assert - await Assert.That(() => _ = new ClassDataSource(typeof(object), null!)).ThrowsExactly(); - } - - [Test] - public async Task TypeIsCorrect() - { - // Arrange - var expected = typeof(object); - var sut = new ClassDataSource(expected); - - // Act - var result = sut.Type; - - // Assert - await Assert.That(result).IsEqualTo(expected); - } - - [Test] - public async Task ParametersIsCorrect() - { - // Arrange - var expected = new[] { new object() }; - var sut = new ClassDataSource(typeof(object), expected); - - // Act - var result = sut.Parameters; - - // Assert - await Assert.That(result).IsEquivalentTo(expected); - } - - [Test] - public async Task ThrowsWhenSourceIsNotEnumerable() - { - // Arrange - var sut = new ClassDataSource(typeof(object)); - var method = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray()).ThrowsExactly(); - } - - [Test] - public async Task GeneratesTestDatWithPrimitiveValues() - { - // Arrange - var expected = new[] - { - new object[] { "hello", 1, new RecordType("world") }, - new object[] { "foo", 2, new RecordType("bar") }, - new object[] { "Han", 3, new RecordType("Solo") } - }; - var sut = new ClassDataSource(typeof(TestSourceWithMixedValues)); - var method = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - - // Act - var actual = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) - .Select(x => x()) - .ToArray(); - - // Assert - await Assert.That(actual).IsEquivalentTo(expected); - } - - private class TestSourceWithMixedValues : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return ["hello", 1, new RecordType("world")]; - yield return ["foo", 2, new RecordType("bar")]; - yield return ["Han", 3, new RecordType("Solo")]; - } - - IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); - } - - [Test] - public async Task ThrowsWhenConstructorParametersDontMatch() - { - // Arrange - var parameters = new object[] { "a", 1 }; - var sut = new ClassDataSource(typeof(TestSourceWithMixedValues), parameters); - var method = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray()).ThrowsException(); - } - - [Test] - public async Task AppliesExpectedConstructorParameters() - { - // Arrange - object[] parameters = [new object[] { "y", 25 }]; - var sut = new ClassDataSource(typeof(DelegatingTestData), parameters); - var method = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - - // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); - - // Assert - await Assert.That(result.Single()).IsEquivalentTo(new object[] { "y", 25 }); - } -} \ No newline at end of file diff --git a/tests/AutoFixture.TUnit.Tests/DataGeneratorMetadataHelper.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataGeneratorMetadataSupport/DataGeneratorMetadataHelper.cs similarity index 72% rename from tests/AutoFixture.TUnit.Tests/DataGeneratorMetadataHelper.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataGeneratorMetadataSupport/DataGeneratorMetadataHelper.cs index 1483b35..6a145da 100644 --- a/tests/AutoFixture.TUnit.Tests/DataGeneratorMetadataHelper.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataGeneratorMetadataSupport/DataGeneratorMetadataHelper.cs @@ -1,7 +1,7 @@ using System.Reflection; using TUnit.Core.Enums; -namespace AutoFixture.TUnit.Tests; +namespace AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; public static class DataGeneratorMetadataHelper { @@ -13,7 +13,7 @@ public static DataGeneratorMetadata CreateDataGeneratorMetadata(Type type, strin public static DataGeneratorMetadata CreateDataGeneratorMetadata(MethodInfo methodInfo) { var parameters = methodInfo.GetParameters(); - var type = methodInfo.ReflectedType ?? methodInfo.DeclaringType!; + var type = methodInfo.ReflectedType ?? methodInfo.DeclaringType; var methodName = methodInfo.Name; var parameterMetadatas = parameters @@ -22,32 +22,32 @@ public static DataGeneratorMetadata CreateDataGeneratorMetadata(MethodInfo metho return new DataGeneratorMetadata { Type = DataGeneratorType.TestParameters, - TestBuilderContext = null!, - TestSessionId = null!, + TestBuilderContext = null, + TestSessionId = null, MembersToGenerate = parameterMetadatas .Cast().ToArray(), TestInformation = new MethodMetadata { Type = type, - TypeInfo = new global::TUnit.Core.ConcreteType(type), + TypeInfo = new ConcreteType(type), Name = methodName, GenericTypeCount = 0, - ReturnTypeInfo = new global::TUnit.Core.ConcreteType(typeof(void)), + ReturnTypeInfo = new ConcreteType(typeof(void)), Class = new ClassMetadata { Type = type, - TypeInfo = new global::TUnit.Core.ConcreteType(type), - Assembly = null!, + TypeInfo = new ConcreteType(type), + Assembly = null, Name = type.Name, - Namespace = null!, + Namespace = null, Parameters = [], Properties = [], - Parent = null! + Parent = null }, Parameters = parameterMetadatas, ReturnType = typeof(void), }, - TestClassInstance = null!, + TestClassInstance = null, ClassInstanceArguments = [] }; } @@ -56,8 +56,8 @@ private static ParameterMetadata CreateParameter(ParameterInfo parameterInfo) { return new ParameterMetadata(parameterInfo.ParameterType) { - Name = parameterInfo.Name!, - TypeInfo = new global::TUnit.Core.ConcreteType(parameterInfo.ParameterType), + Name = parameterInfo.Name, + TypeInfo = new ConcreteType(parameterInfo.ParameterType), ReflectionInfo = parameterInfo }; } diff --git a/tests/AutoFixture.TUnit.Tests/Internal/AutoDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/AutoDataSourceTests/CombineTests.cs similarity index 52% rename from tests/AutoFixture.TUnit.Tests/Internal/AutoDataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/AutoDataSourceTests/CombineTests.cs index c120b30..04c34e5 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/AutoDataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/AutoDataSourceTests/CombineTests.cs @@ -1,14 +1,14 @@ -using AutoFixture.Kernel; +using AutoFixture.Kernel; using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.AutoDataSourceTests; public class AutoDataSourceTests { [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange & Act var sut = new AutoDataSource(() => new DelegatingFixture()); @@ -18,7 +18,7 @@ public async Task SutIsTestDataSource() } [Test] - public async Task SetsPropertiesToExpectedValues() + public async Task Constructor_WhenCreated_SetsPropertiesToExpectedValues() { // Arrange var fixtureFactory = () => new DelegatingFixture(); @@ -28,12 +28,13 @@ public async Task SetsPropertiesToExpectedValues() var sut = new AutoDataSource(fixtureFactory, source); // Assert + // Func needs an explicit type arg, or Assert.That invokes it and asserts on IFixture. await Assert.That>(sut.CreateFixture).IsSameReferenceAs(fixtureFactory); await Assert.That(sut.Source).IsSameReferenceAs(source); } [Test] - public async Task GeneratesTestDataUsingFixture() + public async Task GetData_WhenCalled_GeneratesTestDataUsingFixture() { // Arrange var builder = new CompositeSpecimenBuilder( @@ -48,7 +49,7 @@ public async Task GeneratesTestDataUsingFixture() var method = typeof(SampleTestType).GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).Select(x => x()).ToArray(); + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).Select(x => x()).ToArray(); // Assert await Assert.That(result).IsNotNull(); @@ -56,14 +57,14 @@ public async Task GeneratesTestDataUsingFixture() var item = result.Single(); await Assert.That(item).IsNotNull(); - await Assert.That(item!.Length).IsEqualTo(3); - await Assert.That(item[0]).IsEqualTo("value"); - await Assert.That(item[1]).IsEqualTo(1); - await Assert.That(item[2]).IsEqualTo(12.2); + await Assert.That(item.Length).IsEqualTo(3); + await Assert.That((string)item[0]).IsEqualTo("value"); + await Assert.That((int)item[1]).IsEqualTo(1); + await Assert.That((double)item[2]).IsEqualTo(12.2); } [Test] - public async Task CombinesTestDataFromSourceWithAutoGeneratedValues() + public async Task GetData_WhenSourcePartial_CombinesWithAutoGeneratedValues() { // Arrange var source = new DelegatingDataSource @@ -85,18 +86,18 @@ public async Task CombinesTestDataFromSourceWithAutoGeneratedValues() .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).ToArray(); + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); // Assert await Assert.That(result).IsNotNull(); await Assert.That(result.Length).IsEqualTo(3); - await Assert.That(result[0]).IsEquivalentTo(new object[] { "a", 15, 13.3 }); - await Assert.That(result[1]).IsEquivalentTo(new object[] { "b", 123, 13.3 }); - await Assert.That(result[2]).IsEquivalentTo(new object[] { "c", 999, 13.3 }); + await Assert.That(result[0]).IsEquivalentTo(["a", 15, 13.3]); + await Assert.That(result[1]).IsEquivalentTo(["b", 123, 13.3]); + await Assert.That(result[2]).IsEquivalentTo(["c", 999, 13.3]); } [Test] - public async Task DoesNotGenerateValuesWhenAllValuesProvidedBySource() + public async Task GetData_WhenSourceProvidesAllValues_DoesNotGenerateValues() { // Arrange var source = new DelegatingDataSource @@ -117,23 +118,83 @@ public async Task DoesNotGenerateValuesWhenAllValuesProvidedBySource() .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).ToArray(); + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); // Assert await Assert.That(result).IsNotNull(); await Assert.That(result.Length).IsEqualTo(3); - await Assert.That(result[0]).IsEquivalentTo(new object[] { "a", 85, 913.12 }); - await Assert.That(result[1]).IsEquivalentTo(new object[] { "b", 519, 73.1 }); - await Assert.That(result[2]).IsEquivalentTo(new object[] { "c", 411, 529.6 }); + await Assert.That(result[0]).IsEquivalentTo(["a", 85, 913.12]); + await Assert.That(result[1]).IsEquivalentTo(["b", 519, 73.1]); + await Assert.That(result[2]).IsEquivalentTo(["c", 411, 529.6]); } [Test] - public async Task ReturnsNoTestDataWhenSourceReturnsNoTestData() + public async Task GetData_WhenSourceProvidesMoreValuesThanParameters_Throws() { // Arrange var source = new DelegatingDataSource { - TestData = Array.Empty(), + TestData = [["a", 1, 2.0, "extra"]], + }; + var sut = new AutoDataSource(() => new DelegatingFixture(), source); + var method = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method); + + // Act & Assert + await Assert.That(() => sut.GenerateDataSources(metadata).Select(x => x()).ToArray()) + .ThrowsExactly(); + } + + [Test] + public async Task GetData_WhenClassDataSourceProvidesMoreValuesThanParameters_Throws() + { + // Arrange + var source = new ClassDataSource(typeof(ClassWithExcessTestData)); + var sut = new AutoDataSource(() => new Fixture(), source); + var testMethod = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithSingleParameter)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod); + + // Act & Assert + await Assert.That(async () => + { + await foreach (var rowFunc in sut.GetData(metadata)) + { + _ = await rowFunc(); + } + }).ThrowsExactly(); + } + + [Test] + public async Task GetData_WhenMemberDataSourceProvidesMoreValuesThanParameters_Throws() + { + // Arrange + var source = new MemberDataSource( + typeof(AutoDataSourceTests), + nameof(ExcessMemberData)); + var sut = new AutoDataSource(() => new Fixture(), source); + var testMethod = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithSingleParameter)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod); + + // Act & Assert + await Assert.That(async () => + { + await foreach (var rowFunc in sut.GetData(metadata)) + { + _ = await rowFunc(); + } + }).ThrowsExactly(); + } + + [Test] + public async Task GetData_WhenSourceReturnsNoTestData_ReturnsNoRows() + { + // Arrange + var source = new DelegatingDataSource + { + TestData = [], }; var fixture = new DelegatingFixture(); var sut = new AutoDataSource(() => fixture, source); @@ -141,30 +202,30 @@ public async Task ReturnsNoTestDataWhenSourceReturnsNoTestData() .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).ToArray(); + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); // Assert await Assert.That(result).IsEmpty(); } [Test] - public async Task ThrowsWhenSourceReturnsNull() + public async Task GetData_WhenSourceReturnsNull_Throws() { // Arrange - var source = new DelegatingDataSource { TestData = null! }; + var source = new DelegatingDataSource { TestData = null }; var fixture = new DelegatingFixture(); var sut = new AutoDataSource(() => fixture, source); var method = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)) + await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) .ToArray()) .ThrowsException(); } [Test] - public async Task DoesNotCustomizeFixtureWhenParametersNotCustomized() + public async Task GetData_WhenParametersNotCustomized_DoesNotCustomizeFixture() { // Arrange var customizations = new List(); @@ -177,14 +238,14 @@ public async Task DoesNotCustomizeFixtureWhenParametersNotCustomized() .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); // Act - _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).ToArray(); + _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); // Assert await Assert.That(customizations.Count).IsEqualTo(0); } [Test] - public async Task CustomizesFixtureUsingParameterCustomizations() + public async Task GetData_WhenParametersCustomized_CustomizesFixture() { // Arrange var customizations = new List(); @@ -197,14 +258,14 @@ public async Task CustomizesFixtureUsingParameterCustomizations() .GetMethod(nameof(SampleTestType.TestMethodWithCustomizedParameter)); // Act - _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).Select(x => x()).ToArray(); + _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).Select(x => x()).ToArray(); // Assert await Assert.That(customizations.Count).IsGreaterThan(0); } [Test] - public async Task CustomizationsAreAppliedInExpectedOrder() + public async Task GetData_WhenMultipleCustomizations_AppliesInExpectedOrder() { // Arrange var customizations = new List(); @@ -217,7 +278,7 @@ public async Task CustomizationsAreAppliedInExpectedOrder() .GetMethod(nameof(SampleTestType.TestMethodWithMultipleCustomizations)); // Act - _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method!)).Select(x => x()).ToArray(); + _ = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).Select(x => x()).ToArray(); // Assert using var scope = Assert.Multiple(); @@ -232,4 +293,40 @@ public async Task CustomizationsAreAppliedInExpectedOrder() await Assert.That(compositeCustomizations[0]).IsAssignableTo(); await Assert.That(compositeCustomizations[1]).IsAssignableTo(); } -} \ No newline at end of file + + [Test] + public async Task GetData_WhenSourceYieldsNullRowFactory_Throws() + { + // Arrange + var source = new NullRowFactoryDataSource(); + var sut = new AutoDataSource(() => new DelegatingFixture(), source); + var method = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method); + + // Act & Assert + await Assert.That(async () => + { + await foreach (var rowFunc in sut.GetData(metadata)) + { + _ = await rowFunc(); + } + }).ThrowsExactly(); + } + + public static IEnumerable ExcessMemberData() + { + yield return ["one", "two", "three"]; + } + + private sealed class NullRowFactoryDataSource : BaseDataSourceAttribute + { +#pragma warning disable CS1998 + public override async IAsyncEnumerable>> GetData( + DataGeneratorMetadata dataGeneratorMetadata) + { + yield return null!; + } +#pragma warning restore CS1998 + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs similarity index 69% rename from tests/AutoFixture.TUnit.Tests/Internal/DataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs index 67fb61e..c58a1e2 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/DataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/BaseDataSourceAttributeTests/GetDataRowsAsyncTests.cs @@ -1,13 +1,13 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.BaseDataSourceAttributeTests; public class DataSourceTests { [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange var sut = new DelegatingDataSource(); @@ -17,7 +17,7 @@ public async Task SutIsTestDataSource() } [Test] - public async Task ReturnSingleEmptyArrayWhenMethodHasNoParameters() + public async Task GetDataRowsAsync_WhenMethodHasNoParameters_ReturnsSingleEmptyArray() { // Arrange var sut = new DelegatingDataSource(); @@ -35,10 +35,10 @@ public async Task ReturnSingleEmptyArrayWhenMethodHasNoParameters() } [Test] - public async Task ThrowsWhenNoDataFoundForMethod() + public async Task GetDataRowsAsync_WhenNoDataFound_Throws() { // Arrange - var sut = new DelegatingDataSource { TestData = null! }; + var sut = new DelegatingDataSource { TestData = null }; var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithSingleParameter)); @@ -47,7 +47,7 @@ public async Task ThrowsWhenNoDataFoundForMethod() } [Test] - public async Task ReturnSingleArrayWithSingleItemWhenMethodHasSingleParameter() + public async Task GetDataRowsAsync_WhenMethodHasSingleParameter_ReturnsSingleItemArray() { // Arrange var sut = new DelegatingDataSource @@ -63,22 +63,21 @@ public async Task ReturnSingleArrayWithSingleItemWhenMethodHasSingleParameter() // Assert await Assert.That(result.Length).IsEqualTo(1); var testData = result.Single()(); - await Assert.That(testData!.Length).IsEqualTo(1); - await Assert.That(testData[0]).IsEqualTo("hello"); + await Assert.That(testData.Length).IsEqualTo(1); + await Assert.That((string)testData[0]).IsEqualTo("hello"); } [Test] - public async Task ReturnsArgumentsFittingTestParameters() + public async Task GetDataRowsAsync_WhenCalled_ReturnsArgumentsFittingParameters() { // Arrange - var testData = new[] - { - new object[] { "hello", 16, 32.86d }, - new object[] { null!, -1, -20.22 }, - new object[] { "one", 2 }, - new object[] { null! }, - new object[] { }, - }; + object[][] testData = [ + [ "hello", 16, 32.86d ], + [null, -1, -20.22], + ["one", 2], + [null], + [], + ]; var sut = new DelegatingDataSource { TestData = testData }; var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); @@ -93,15 +92,15 @@ public async Task ReturnsArgumentsFittingTestParameters() foreach (var a in actual) { - await Assert.That(a!.Length).IsBetween(0, 3); + await Assert.That(a.Length).IsBetween(0, 3); } } [Test] - public async Task ThrowsWhenTestDataContainsMoreArgumentsThanParameters() + public async Task GetDataRowsAsync_WhenMoreArgumentsThanParameters_Throws() { // Arrange - var testData = new[] { new object[] { "hello", 16, 32.86d, "extra" } }; + object[][] testData = [[ "hello", 16, 32.86d, "extra" ]]; var sut = new DelegatingDataSource { TestData = testData }; var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); @@ -109,4 +108,4 @@ public async Task ThrowsWhenTestDataContainsMoreArgumentsThanParameters() // Act & Assert await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)).ToArray()).ThrowsExactly(); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs new file mode 100644 index 0000000..273ca6e --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/ClassDataSourceTests/ConstructionTests.cs @@ -0,0 +1,74 @@ +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Internal.DataSources.ClassDataSourceTests; + +/// +/// Internal ClassDataSource construction leftovers. Row shapes via AutoClassDataSourceAttribute. +/// +public class ConstructionTests +{ + [Test] + public async Task Constructor_WhenCreated_IsDataSource() + { + var sut = new ClassDataSource(typeof(object)); + + await Assert.That(sut).IsAssignableTo(); + } + + [Test] + public async Task Constructor_WhenTypeIsNull_ThrowsArgumentNullException() + { + await Assert.That(() => _ = new ClassDataSource(null)).ThrowsExactly(); + } + + [Test] + public async Task Constructor_WhenParametersIsNull_ThrowsArgumentNullException() + { + await Assert.That(() => _ = new ClassDataSource(typeof(object), null)).ThrowsExactly(); + } + + [Test] + public async Task Type_WhenRead_ReturnsConstructorArgument() + { + var expected = typeof(object); + var sut = new ClassDataSource(expected); + + await Assert.That(sut.Type).IsEqualTo(expected); + } + + [Test] + public async Task Parameters_WhenRead_ReturnsConstructorArguments() + { + object[] expected = [new object()]; + var sut = new ClassDataSource(typeof(object), expected); + + await Assert.That(sut.Parameters).IsEquivalentTo(expected); + } + + [Test] + public async Task GetData_WhenConstructorParametersDontMatch_Throws() + { + object[] parameters = ["a", 1]; + var sut = new ClassDataSource(typeof(object), parameters); + var method = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); + + await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray()) + .ThrowsException(); + } + + [Test] + public async Task GetData_WhenConstructorParametersMatch_AppliesThem() + { + object[] parameters = [new object[] { "y", 25 }]; + var sut = new ClassDataSource(typeof(DelegatingTestData), parameters); + var method = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); + + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray(); + + await Assert.That(result.Single()).IsEquivalentTo(["y", 25]); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/FieldDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/FieldDataSourceTests/ConstructionTests.cs similarity index 65% rename from tests/AutoFixture.TUnit.Tests/Internal/FieldDataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/FieldDataSourceTests/ConstructionTests.cs index 4f0d802..84c6d81 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/FieldDataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/FieldDataSourceTests/ConstructionTests.cs @@ -1,9 +1,9 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.FieldDataSourceTests; public class FieldDataSourceTests { @@ -17,7 +17,7 @@ public class FieldDataSourceTests public static object NonEnumerableField = new object(); [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange var sourceField = typeof(FieldDataSourceTests) @@ -29,14 +29,14 @@ public async Task SutIsTestDataSource() } [Test] - public async Task ThrowsWhenConstructedWithNullField() + public async Task Constructor_WhenFieldIsNull_Throws() { // Act & Assert - await Assert.That(() => new FieldDataSource(null!)).ThrowsExactly(); + await Assert.That(() => new FieldDataSource(null)).ThrowsExactly(); } [Test] - public async Task FieldIsCorrect() + public async Task Field_WhenRead_ReturnsConstructorArgument() { // Arrange var expected = typeof(FieldDataSourceTests) @@ -51,7 +51,7 @@ public async Task FieldIsCorrect() } [Test] - public async Task ThrowsWhenInvokedWithNullTestMethod() + public async Task GetData_WhenTestMethodIsNull_Throws() { // Arrange var sourceField = typeof(FieldDataSourceTests) @@ -59,11 +59,11 @@ public async Task ThrowsWhenInvokedWithNullTestMethod() var sut = new FieldDataSource(sourceField); // Act & Assert - await Assert.That(() => sut.GenerateDataSources(null!).ToArray()).ThrowsExactly(); + await Assert.That(() => sut.GenerateDataSources(null).ToArray()).ThrowsExactly(); } [Test] - public async Task ThrowsWhenSourceIsNotEnumerable() + public async Task GetData_WhenSourceIsScalar_ReturnsSingleRow() { // Arrange var sourceField = typeof(FieldDataSourceTests) @@ -72,20 +72,25 @@ public async Task ThrowsWhenSourceIsNotEnumerable() var method = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)).ToArray()).ThrowsExactly(); + // Act + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) + .Select(x => x()) + .ToArray(); + + // Assert + await Assert.That(result.Length).IsEqualTo(1); + await Assert.That(result[0]).IsEquivalentTo([NonEnumerableField]); } [Test] - public async Task GeneratesTestDataMatchingTestParameters() + public async Task GetData_WhenCalled_ReturnsDataMatchingParameters() { // Arrange - var expected = new[] - { - new object[] { "hello", 1, new RecordType("world") }, - new object[] { "foo", 2, new RecordType("bar") }, - new object[] { "Han", 3, new RecordType("Solo") } - }; + object[][] expected = [ + [ "hello", 1, new RecordType("world") ], + ["foo", 2, new RecordType("bar")], + ["Han", 3, new RecordType("Solo")] + ]; var sourceField = typeof(FieldDataSourceTests) .GetField(nameof(TestDataFieldWithRecordValues)); var sut = new FieldDataSource(sourceField); @@ -107,4 +112,4 @@ public async Task GeneratesTestDataMatchingTestParameters() ["foo", 2, new RecordType("bar")], ["Han", 3, new RecordType("Solo")] ]; -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/InlineDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/InlineDataSourceTests/ConstructionTests.cs similarity index 61% rename from tests/AutoFixture.TUnit.Tests/Internal/InlineDataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/InlineDataSourceTests/ConstructionTests.cs index 85847b9..fd6c575 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/InlineDataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/InlineDataSourceTests/ConstructionTests.cs @@ -1,36 +1,35 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; -using TUnit.Assertions.Extensions; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.InlineDataSourceTests; public class InlineDataSourceTests { [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange // Act - var sut = new InlineDataSource([ - ]); + var sut = new InlineDataSource([]); // Assert await Assert.That(sut).IsAssignableTo(); } [Test] - public async Task InitializeWithNullValuesThrows() + public async Task Constructor_WhenValuesIsNull_Throws() { // Arrange // Act & Assert await Assert.That(() => - new InlineDataSource(null!)).ThrowsExactly(); + new InlineDataSource(null)).ThrowsExactly(); } [Test] - public async Task ValuesIsCorrect() + public async Task Values_WhenRead_ReturnsConstructorArguments() { // Arrange - var expectedValues = Array.Empty(); + object[] expectedValues = []; var sut = new InlineDataSource(expectedValues); // Act var result = sut.Values; @@ -39,21 +38,24 @@ public async Task ValuesIsCorrect() } [Test] - public async Task GetTestDataWithNullMethodThrows() + public async Task GetData_WhenMethodIsNull_Throws() { // Arrange - var sut = new InlineDataSource([ - ]); - // Act & Assert - await Assert.That(() => - sut.GenerateDataSources(null!).ToArray()).ThrowsExactly(); + var sut = new InlineDataSource([]); + // Act & Assert - call GetData directly so InlineDataSource's null guard is hit + await Assert.That(async () => + { + await foreach (var _ in sut.GetData(null)) + { + } + }).ThrowsExactly(); } [Test] - public async Task SourceThrowsWhenArgumentCountExceedParameterCount() + public async Task GetData_WhenArgumentCountExceedsParameterCount_Throws() { // Arrange - var values = new object[] { "aloha", 42, 12.3d, "extra" }; + object[] values = ["aloha", 42, 12.3d, "extra"]; var sut = new InlineDataSource(values); var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); @@ -66,10 +68,10 @@ await Assert.That(() => } [Test] - public async Task ReturnsTestDataWhenArgumentCountMatchesParameterCount() + public async Task GetData_WhenArgumentCountMatchesParameterCount_ReturnsTestData() { // Arrange - var values = new object[] { "aloha", 42, 12.3d }; + object[] values = ["aloha", 42, 12.3d]; var sut = new InlineDataSource(values); var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); @@ -83,10 +85,10 @@ public async Task ReturnsTestDataWhenArgumentCountMatchesParameterCount() } [Test] - public async Task ReturnsAllArgumentsWhenArgumentCountLessThanParameterCount() + public async Task GetData_WhenArgumentCountLessThanParameterCount_ReturnsAllArguments() { // Arrange - var values = new object[] { "aloha", 42 }; + object[] values = ["aloha", 42]; var sut = new InlineDataSource(values); var testMethod = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); @@ -98,4 +100,4 @@ public async Task ReturnsAllArgumentsWhenArgumentCountLessThanParameterCount() var testData = await Assert.That(result).HasSingleItem(); await Assert.That(testData).IsEqualTo(values); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/MemberDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MemberDataSourceTests/ConstructionTests.cs similarity index 56% rename from tests/AutoFixture.TUnit.Tests/Internal/MemberDataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/MemberDataSourceTests/ConstructionTests.cs index 8b30299..dfd2652 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/MemberDataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MemberDataSourceTests/ConstructionTests.cs @@ -1,21 +1,21 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; -using TUnit.Assertions.Extensions; using PropertyDataSource = AutoFixture.TUnit.Internal.PropertyDataSource; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.MemberDataSourceTests; public class MemberDataSourceTests { public static object NonTestDataField = new(); public static object NonTestDataProperty => new(); public static object NonTestDataMethod() => new(); - public static IEnumerable EmptyTestDataField = Array.Empty(); - public static IEnumerable EmptyTestData => Array.Empty(); - public static IEnumerable GetEmptyTestData() => Array.Empty(); + public static IEnumerable EmptyTestDataField = []; + public static IEnumerable EmptyTestData => []; + public static IEnumerable GetEmptyTestData() => []; [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange & Act var sut = new MemberDataSource( @@ -27,38 +27,38 @@ public async Task SutIsTestDataSource() } [Test] - public async Task ThrowsWhenTypeIsNull() + public async Task Constructor_WhenTypeIsNull_Throws() { // Arrange var method = nameof(GetEmptyTestData); // Act & Assert - await Assert.That(() => new MemberDataSource(null!, method)).ThrowsExactly(); + await Assert.That(() => new MemberDataSource(null, method)).ThrowsExactly(); } [Test] - public async Task ThrowsWhenNameIsNull() + public async Task Constructor_WhenNameIsNull_Throws() { // Arrange var type = typeof(MemberDataSourceTests); // Act & Assert - await Assert.That(() => new MemberDataSource(type, null!)).ThrowsExactly(); + await Assert.That(() => new MemberDataSource(type, null)).ThrowsExactly(); } [Test] - public async Task ThrowsWhenArgumentsIsNull() + public async Task Constructor_WhenArgumentsIsNull_Throws() { // Arrange var type = typeof(MemberDataSourceTests); var method = nameof(GetEmptyTestData); // Act & Assert - await Assert.That(() => new MemberDataSource(type, method, null!)).ThrowsExactly(); + await Assert.That(() => new MemberDataSource(type, method, null)).ThrowsExactly(); } [Test] - public async Task InitializesTypeProperty() + public async Task Type_WhenRead_ReturnsConstructorArgument() { // Arrange var type = typeof(MemberDataSourceTests); @@ -77,7 +77,7 @@ public async Task InitializesTypeProperty() [Arguments(nameof(EmptyTestDataField), typeof(FieldDataSource))] [Arguments(nameof(EmptyTestData), typeof(PropertyDataSource))] [Arguments(nameof(GetEmptyTestData), typeof(MethodDataSource))] - public async Task InitializesSourceProperty(string memberName, Type expectedInnerSourceType) + public async Task Source_WhenRead_ReturnsResolvedMember(string memberName, Type expectedInnerSourceType) { // Arrange var type = typeof(MemberDataSourceTests); @@ -90,7 +90,7 @@ public async Task InitializesSourceProperty(string memberName, Type expectedInne } [Test] - public async Task ThrowsWhenSourceDoesNotExist() + public async Task GetData_WhenSourceDoesNotExist_Throws() { // Arrange var type = typeof(MemberDataSourceTests); @@ -103,12 +103,24 @@ public async Task ThrowsWhenSourceDoesNotExist() [Arguments(nameof(NonTestDataField))] [Arguments(nameof(NonTestDataProperty))] [Arguments(nameof(NonTestDataMethod))] - public async Task ThrowsWhenSourceDoesNotReturnTestData(string memberName) + public async Task GetData_WhenSourceReturnsScalar_ReturnsSingleRow(string memberName) { // Arrange var type = typeof(MemberDataSourceTests); + var sut = new MemberDataSource(type, memberName); + var testMethod = typeof(SampleTestType) + .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); + var metadata = DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!); - // Act & Assert - await Assert.That(() => _ = new DelegatingMemberDataSource(type, memberName)).ThrowsExactly(); + // Act + var result = new List(); + await foreach (var rowFunc in sut.GetData(metadata)) + { + result.Add(await rowFunc()); + } + + // Assert + await Assert.That(result.Count).IsEqualTo(1); + await Assert.That(result[0]!.Length).IsEqualTo(1); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs new file mode 100644 index 0000000..3dc4c15 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ConstructionTests.cs @@ -0,0 +1,71 @@ +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; +using AutoFixture.TUnit.Tests.TestTypes; +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.Internal.DataSources.MethodDataSourceTests; + +/// +/// Internal MethodDataSource construction and wiring leftovers. +/// Row shapes are covered via AutoMemberDataSourceAttribute. +/// +public class ConstructionTests +{ + public static IEnumerable ObjectArrayRows() + { + yield return ["hello", 1, new RecordType("world")]; + yield return ["foo", 2, new RecordType("bar")]; + } + + [Test] + public async Task Constructor_WhenCreated_IsDataSource() + { + var methodInfo = typeof(ConstructionTests).GetMethod(nameof(this.Constructor_WhenCreated_IsDataSource)); + var sut = new MethodDataSource(methodInfo); + + await Assert.That(sut).IsAssignableTo(); + } + + [Test] + public async Task Constructor_WhenMethodInfoIsNull_ThrowsArgumentNullException() + { + await Assert.That(() => new MethodDataSource(null)).ThrowsExactly(); + } + + [Test] + public async Task Constructor_WhenArgumentsIsNull_ThrowsArgumentNullException() + { + var methodInfo = typeof(ConstructionTests).GetMethod(nameof(this.Constructor_WhenCreated_IsDataSource)); + + await Assert.That(() => new MethodDataSource(methodInfo, null)).ThrowsExactly(); + } + + [Test] + public async Task Constructor_WhenArgumentsProvided_SetsMembers() + { + var methodInfo = typeof(ConstructionTests).GetMethod(nameof(this.Constructor_WhenCreated_IsDataSource)); + object[] arguments = [new object()]; + + var sut = new MethodDataSource(methodInfo, arguments); + + await Assert.That(sut.MethodInfo).IsEqualTo(methodInfo); + await Assert.That(sut.Arguments).IsEquivalentTo(arguments); + } + + [Test] + public async Task GetData_WhenInvoked_CallsSourceMethod() + { + object[][] expected = [ + [ "hello", 1, new RecordType("world") ], + ["foo", 2, new RecordType("bar")] + ]; + var sourceMethod = typeof(ConstructionTests).GetMethod(nameof(ObjectArrayRows)); + var testMethod = typeof(SampleTestType).GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); + var sut = new MethodDataSource(sourceMethod); + + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod)) + .Select(x => x()); + + await Assert.That(result).IsEquivalentTo(expected); + } +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs new file mode 100644 index 0000000..156150c --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/MethodDataSourceTests/ResultShapeLeftoverTests.cs @@ -0,0 +1,29 @@ +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; +using AutoFixture.TUnit.Tests.TestTypes; + +namespace AutoFixture.TUnit.Tests.Internal.DataSources.MethodDataSourceTests; + +/// +/// Leftover Internal coverage for branches awkward to express via public attributes +/// (nested Task unwrap). Prefer AutoMemberDataSourceAttribute shape tests for normal cases. +/// +public class ResultShapeLeftoverTests +{ + [Test] + public async Task GetData_WhenNestedTaskOfTupleSequence_UnwrapsAllTasksAndExpandsTuples() + { + var sourceMethod = typeof(ResultShapeLeftoverTests).GetMethod(nameof(NestedTaskOfTupleSequence)); + var testMethod = typeof(SampleTestType).GetMethod(nameof(SampleTestType.TestMethodWithMultipleParameters)); + var sut = new MethodDataSource(sourceMethod!); + + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testMethod!)) + .Select(x => x()) + .ToArray(); + + await Assert.That(result).IsEquivalentTo([["a", 1], ["b", 2]]); + } + + public static Task>> NestedTaskOfTupleSequence() => + Task.FromResult(Task.FromResult>([("a", 1), ("b", 2)])); +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/PropertyDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/PropertyDataSourceTests/ConstructionTests.cs similarity index 68% rename from tests/AutoFixture.TUnit.Tests/Internal/PropertyDataSourceTests.cs rename to tests/AutoFixture.TUnit.Tests/Internal/DataSources/PropertyDataSourceTests/ConstructionTests.cs index 588ad52..d94ecfb 100644 --- a/tests/AutoFixture.TUnit.Tests/Internal/PropertyDataSourceTests.cs +++ b/tests/AutoFixture.TUnit.Tests/Internal/DataSources/PropertyDataSourceTests/ConstructionTests.cs @@ -1,15 +1,15 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Tests.Internal.DataGeneratorMetadataSupport; using AutoFixture.TUnit.Tests.TestTypes; using TestTypeFoundation; -using TUnit.Assertions.Extensions; using PropertyDataSource = AutoFixture.TUnit.Internal.PropertyDataSource; -namespace AutoFixture.TUnit.Tests.Internal; +namespace AutoFixture.TUnit.Tests.Internal.DataSources.PropertyDataSourceTests; public class PropertyDataSourceTests { [Test] - public async Task SutIsTestDataSource() + public async Task Constructor_WhenCreated_IsDataSource() { // Arrange var sourceProperty = typeof(PropertyDataSourceTests) @@ -30,14 +30,14 @@ public async Task SutIsTestDataSource() public static object NonEnumerableProperty => new object(); [Test] - public async Task ThrowsWhenConstructedWithNullProperty() + public async Task Constructor_WhenPropertyIsNull_Throws() { // Act & Assert - await Assert.That(() => new PropertyDataSource(null!)).ThrowsExactly(); + await Assert.That(() => new PropertyDataSource(null)).ThrowsExactly(); } [Test] - public async Task PropertyIsCorrect() + public async Task Property_WhenRead_ReturnsConstructorArgument() { // Arrange var expected = typeof(PropertyDataSourceTests) @@ -52,7 +52,7 @@ public async Task PropertyIsCorrect() } [Test] - public async Task ThrowsWhenInvokedWithNullTestMethod() + public async Task GetData_WhenTestMethodIsNull_Throws() { // Arrange var sourceProperty = typeof(PropertyDataSourceTests) @@ -60,11 +60,11 @@ public async Task ThrowsWhenInvokedWithNullTestMethod() var sut = new PropertyDataSource(sourceProperty); // Act & Assert - await Assert.That(() => sut.GenerateDataSources(null!).ToArray()).ThrowsExactly(); + await Assert.That(() => sut.GenerateDataSources(null).ToArray()).ThrowsExactly(); } [Test] - public async Task ThrowsWhenSourceIsNotEnumerable() + public async Task GetData_WhenSourceIsScalar_ReturnsSingleRow() { // Arrange var sourceProperty = typeof(PropertyDataSourceTests) @@ -73,22 +73,25 @@ public async Task ThrowsWhenSourceIsNotEnumerable() var method = typeof(SampleTestType) .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) + // Act + var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(method)) + .Select(x => x()) + .ToArray(); - .ToArray()).ThrowsExactly(); + // Assert + await Assert.That(result.Length).IsEqualTo(1); + await Assert.That(result[0].Length).IsEqualTo(1); } [Test] - public async Task GeneratesTestDataMatchingTestParameters() + public async Task GetData_WhenCalled_ReturnsDataMatchingParameters() { // Arrange - var expected = new[] - { - new object[] { "hello", 1, new RecordType("world") }, - new object[] { "foo", 2, new RecordType("bar") }, - new object[] { "Han", 3, new RecordType("Solo") } - }; + object[][] expected = [ + [ "hello", 1, new RecordType("world") ], + ["foo", 2, new RecordType("bar")], + ["Han", 3, new RecordType("Solo")] + ]; var sourceProperty = typeof(PropertyDataSourceTests) .GetProperty(nameof(TestDataPropertyWithRecordValues)); var sut = new PropertyDataSource(sourceProperty); @@ -112,15 +115,14 @@ public async Task GeneratesTestDataMatchingTestParameters() ]; [Test] - public async Task ReturnsNullArguments() + public async Task GetData_WhenSourceReturnsNull_ReturnsNullArguments() { // Arrange - var expected = new[] - { - new object[] { null!, 1, null! }, - new object[] { null!, 2, null! }, - new object[] { null!, 3, null! } - }; + object[][] expected = [ + [ null, 1, null ], + [null, 2, null], + [null, 3, null] + ]; var sourceProperty = typeof(PropertyDataSourceTests) .GetProperty(nameof(TestDataPropertyWithNullValues)); var sut = new PropertyDataSource(sourceProperty); @@ -138,8 +140,8 @@ public async Task ReturnsNullArguments() public static IEnumerable TestDataPropertyWithNullValues => [ - [null!, 1, null!], - [null!, 2, null!], - [null!, 3, null!] + [null, 1, null], + [null, 2, null], + [null, 3, null] ]; -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/Internal/MethodDataSourceTests.cs b/tests/AutoFixture.TUnit.Tests/Internal/MethodDataSourceTests.cs deleted file mode 100644 index edbddd8..0000000 --- a/tests/AutoFixture.TUnit.Tests/Internal/MethodDataSourceTests.cs +++ /dev/null @@ -1,106 +0,0 @@ -using AutoFixture.TUnit.Internal; -using AutoFixture.TUnit.Tests.TestTypes; -using TestTypeFoundation; -using TUnit.Assertions.Extensions; - -namespace AutoFixture.TUnit.Tests.Internal; - -public class MethodDataSourceTests -{ - public static IEnumerable GetTestDataFieldWithMixedValues() - { - yield return ["hello", 1, new RecordType("world")]; - yield return ["foo", 2, new RecordType("bar")]; - yield return ["Han", 3, new RecordType("Solo")]; - } - - [Test] - public async Task SutIsTestDataSource() - { - // Arrange - var methodInfo = typeof(MethodDataSourceTests) - .GetMethod(nameof(this.SutIsTestDataSource)); - - // Act - var sut = new MethodDataSource(methodInfo); - - // Assert - await Assert.That(sut).IsAssignableTo(); - } - - [Test] - public async Task ThrowsWhenMethodInfoIsNull() - { - // Act & Assert - await Assert.That(() => - new MethodDataSource(null!)).ThrowsExactly(); - } - - [Test] - public async Task ThrowsWhenArgumentsIsNull() - { - // Arrange - var methodInfo = typeof(MethodDataSourceTests) - .GetMethod(nameof(this.SutIsTestDataSource)); - - // Act & Assert - await Assert.That(() => - new MethodDataSource(methodInfo, null!)).ThrowsExactly(); - } - - [Test] - public async Task ConstructorSetsProperties() - { - // Arrange - var methodInfo = typeof(MethodDataSourceTests) - .GetMethod(nameof(this.SutIsTestDataSource)); - var arguments = new[] { new object() }; - - // Act - var sut = new MethodDataSource(methodInfo, arguments); - - // Assert - await Assert.That(sut.MethodInfo).IsEqualTo(methodInfo); - await Assert.That(sut.Arguments).IsEquivalentTo(arguments); - } - - [Test] - public async Task GetTestDataInvokesMethodInfo() - { - // Arrange - var expected = new[] - { - new object[] { "hello", 1, new RecordType("world") }, - new object[] { "foo", 2, new RecordType("bar") }, - new object[] { "Han", 3, new RecordType("Solo") } - }; - var testDataSource = typeof(MethodDataSourceTests) - .GetMethod(nameof(GetTestDataFieldWithMixedValues)); - var testData = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - var sut = new MethodDataSource(testDataSource); - - // Act - var result = sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testData)) - .Select(x => x()); - - // Assert - await Assert.That(result).IsEquivalentTo(expected); - } - - [Test] - public async Task ThrowsWhenMemberDoesNotReturnAnEnumerableValue() - { - // Arrange - var dataSource = typeof(MethodDataSourceTests) - .GetMethod(nameof(NonEnumerableTestData)); - var testData = typeof(SampleTestType) - .GetMethod(nameof(SampleTestType.TestMethodWithReferenceTypeParameter)); - var sut = new MethodDataSource(dataSource); - - // Act & Assert - await Assert.That(() => sut.GenerateDataSources(DataGeneratorMetadataHelper.CreateDataGeneratorMetadata(testData)).ToArray()).ThrowsExactly(); - } - - public static object NonEnumerableTestData() => new(); -} \ No newline at end of file diff --git a/tests/AutoFixture.TUnit.Tests/Scenario.cs b/tests/AutoFixture.TUnit.Tests/Scenario.cs deleted file mode 100644 index 2f273df..0000000 --- a/tests/AutoFixture.TUnit.Tests/Scenario.cs +++ /dev/null @@ -1,563 +0,0 @@ -using System.Collections; -using System.ComponentModel.DataAnnotations; -using AutoFixture.TUnit.Tests.TestTypes; -using TestTypeFoundation; -using ConcreteType = TestTypeFoundation.ConcreteType; - -namespace AutoFixture.TUnit.Tests; - -public class Scenario -{ - [Test, AutoDataSource] - public async Task AutoDataProvidesCorrectInteger(int primitiveValue) - { - await Assert.That(primitiveValue).IsNotEqualTo(0); - } - - [Test, AutoDataSource] - public async Task AutoDataProvidesCorrectString(string text) - { - await Assert.That(text).StartsWith("text"); - } - - [Test, AutoDataSource] - public async Task AutoDataProvidesCorrectObject(PropertyHolder ph) - { - await Assert.That(ph).IsNotNull(); - await Assert.That(ph.Property).IsNotNull(); - } - - [Test, AutoDataSource] - public async Task AutoDataProvidesMultipleObjects(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] - [AutoArguments("foo")] - [AutoArguments("foo", "bar")] - public async Task InlineAutoDataUsesSuppliedDataValues(string s1, string s2) - { - await Assert.That(s1).IsEqualTo("foo"); - await Assert.That(s2).IsNotNull(); - } - - [Test] - [AutoArguments("foo")] - [AutoArguments("foo", "bar")] - public async Task InlineAutoDataSuppliesDataSpecimens(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 InlineAutoDataSuppliesDataSpecimensOnlyForNonProvidedValues(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"); - } - - // This test and its associated types is used to document one of the - // InlineAutoDataAttribute constructor overloads. - [Test] - [MyCustomAutoArguments(1337)] - [MyCustomAutoArguments(1337, 7)] - [MyCustomAutoArguments(1337, 7, 42)] -#pragma warning disable xUnit1026 // Test methods should use all of their parameters - it's required by the test logic. - public async Task CustomInlineDataSuppliesExtraValues(int x, int y, int z) -#pragma warning restore xUnit1026 // Test methods should use all of their parameters - { - await Assert.That(x).IsEqualTo(1337); - - // y can vary, so we can't express any meaningful assertion for it. - await Assert.That(z).IsEqualTo(42); - } - - public class MyCustomAutoArgumentsAttribute - : AutoArgumentsAttribute - { - public MyCustomAutoArgumentsAttribute(params object[] values) - : base(() => new Fixture().Customize(new TheAnswer()), values) - { - } - } - - [Test, AutoMemberDataSource(nameof(StringData))] - public async Task MemberAutoDataUsesSuppliedDataValues(string s1, string s2) - { - await Assert.That(s1).IsEqualTo("foo"); - await Assert.That(s2).IsNotNull(); - } - - [Test, AutoMemberDataSource(nameof(StringData))] - public async Task MemberAutoDataSuppliesDataSpecimens(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 MemberAutoDataSuppliesDataSpecimensOnlyForNonProvidedValues(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 MemberAutoDataCanBeParametrized(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 CustomMemberAutoDataSuppliesExtraValues(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 CustomMemberAutoDataCanBeParametrized(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); - } - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameter([Frozen] Guid g1, Guid g2) - { - await Assert.That(g2).IsEqualTo(g1); - } - - [Test, AutoDataSource] - public async Task FreezeSecondParameterOnlyFreezesSubsequentParameters(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 IntroductoryTest(int expectedNumber, MyClass sut) - { - // Arrange - // Act - int result = sut.Echo(expectedNumber); - - // Assert - await Assert.That(result).IsEqualTo(expectedNumber); - } - - [Test, AutoDataSource] - public async Task ModestCreatesParameterWithModestConstructor([Modest] MultiUnorderedConstructorType p) - { - await Assert.That(string.IsNullOrEmpty(p.Text)).IsTrue(); - await Assert.That(p.Number).IsEqualTo(0); - } - - [Test, AutoDataSource] - public async Task GreedyCreatesParameterWithGreedyConstructor([Greedy] MultiUnorderedConstructorType p) - { - await Assert.That(string.IsNullOrEmpty(p.Text)).IsFalse(); - await Assert.That(p.Number).IsNotEqualTo(0); - } - - [Test, AutoDataSource] - public async Task BothFrozenAndGreedyAttributesCanBeAppliedToSameParameter( - [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 FavorArraysCausesArrayConstructorToBeInjectedWithFrozenItems([Frozen] int[] numbers, - [FavorArrays] ItemContainer container) - { - await Assert.That(numbers.SequenceEqual(container.Items)).IsTrue(); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterShouldAssignSameInstanceToSecondParameter([Frozen] string p1, - string p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByExactTypeShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.ExactType)] ConcreteType p1, - ConcreteType p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByExactTypeShouldNotAssignSameInstanceToSecondParameterOfDifferentType( - [Frozen(Matching.ExactType)] ConcreteType p1, - object p2) - { - await Assert.That(p2).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByDirectBaseTypeShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.DirectBaseType)] ConcreteType p1, - AbstractType p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByDirectBaseTypeShouldNotAssignSameInstanceToSecondParameterOfIndirectBaseType( - [Frozen(Matching.DirectBaseType)] ConcreteType p1, - object p2) - { - await Assert.That(p2).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByDirectBaseTypeShouldNotAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.DirectBaseType)] ConcreteType p1, - ConcreteType p2) - { - await Assert.That(p2).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByExactOrDirectBaseTypeShouldAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.ExactType | Matching.DirectBaseType)] - ConcreteType p1, - ConcreteType p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByInterfaceShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.ImplementedInterfaces)] - NoopInterfaceImplementer p1, - IInterface p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByInterfaceShouldNotAssignSameInstanceToSecondParameterOfNonInterfaceType( - [Frozen(Matching.ImplementedInterfaces)] - NoopInterfaceImplementer p1, - object p2) - { - await Assert.That(p2).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByInterfaceShouldNotAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.ImplementedInterfaces)] - NoopInterfaceImplementer p1, - NoopInterfaceImplementer p2) - { - await Assert.That(p2).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByDirectOrInterfaceShouldAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.ExactType | Matching.ImplementedInterfaces)] - NoopInterfaceImplementer p1, - NoopInterfaceImplementer p2) - { - await Assert.That(p2).IsEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByParameterWithSameNameShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.ParameterName)] string parameter, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsEqualTo(parameter); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByParameterWithDifferentNameShouldNotAssignSameInstanceToSecondParameter( - [Frozen(Matching.ParameterName)] string p1, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByParameterWithDifferentNameShouldNotAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.ParameterName)] string p1, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByPropertyWithSameNameShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.PropertyName)] string property, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsEqualTo(property); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByPropertyWithDifferentNameShouldNotAssignSameInstanceToSecondParameter( - [Frozen(Matching.PropertyName)] string p1, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByPropertyWithDifferentNameShouldNotAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.PropertyName)] string p1, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByFieldWithSameNameShouldAssignSameInstanceToSecondParameter( - [Frozen(Matching.FieldName)] string field, - FieldHolder p2) - { - await Assert.That(p2.Field).IsEqualTo(field); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByFieldWithDifferentNameShouldNotAssignSameInstanceToSecondParameter( - [Frozen(Matching.FieldName)] string p1, - FieldHolder p2) - { - await Assert.That(p2.Field).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByFieldWithDifferentNameShouldNotAssignSameInstanceToSecondParameterOfSameType( - [Frozen(Matching.FieldName)] string p1, - FieldHolder p2) - { - await Assert.That(p2.Field).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithSameNameShouldAssignSameInstanceToMatchingParameter( - [Frozen(Matching.MemberName)] string parameter, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsEqualTo(parameter); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToParameter( - [Frozen(Matching.MemberName)] string p1, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToParameterOfSameType( - [Frozen(Matching.MemberName)] string p1, - SingleParameterType p2) - { - await Assert.That(p2.Parameter).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithSameNameShouldAssignSameInstanceToMatchingProperty( - [Frozen(Matching.MemberName)] string property, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsEqualTo(property); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToProperty( - [Frozen(Matching.MemberName)] string p1, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToPropertyOfSameType( - [Frozen(Matching.MemberName)] string p1, - PropertyHolder p2) - { - await Assert.That(p2.Property).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithSameNameShouldAssignSameInstanceToMatchingField( - [Frozen(Matching.MemberName)] string field, - FieldHolder p2) - { - await Assert.That(p2.Field).IsEqualTo(field); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToField( - [Frozen(Matching.MemberName)] string p1, - FieldHolder p2) - { - await Assert.That(p2.Field).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeFirstParameterByMemberWithDifferentNameShouldNotAssignSameInstanceToFieldOfSameType( - [Frozen(Matching.MemberName)] string p1, - FieldHolder p2) - { - await Assert.That(p2.Field).IsNotEqualTo(p1); - } - - [Test, AutoDataSource] - public async Task FreezeParameterWithStringLengthConstraintShouldCreateConstrainedSpecimen( - [Frozen, StringLength(3)] string p) - { - await Assert.That(p.Length == 3).IsTrue(); - } - - [Test, AutoClassDataSource(typeof(StringDataClass))] - public async Task ClassAutoDataUsesValuesSuppliedByClass(string s1, string s2, string s3) - { - await Assert.That(new[] { "foo", "dim" }).Contains(s1); - await Assert.That(s2).IsNotEmpty(); - await Assert.That(s3).IsNotEmpty(); - } - - [Test, AutoClassDataSource(typeof(StringDataClass))] - public async Task ClassAutoDataSuppliesDataSpecimens(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 ClassAutoDataSuppliesDataOfMixedTypes(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 ClassAutoDataCanBeParameterized(int p1, string p2, double p3, RecordType p4) - { - var actual = new object[] { p1, p2, p3 }; - var expected = new object[] { 28, "bar", 93.102 }; - - await Assert.That(actual).IsEquivalentTo(expected); - await Assert.That(p4).IsNotNull(); - } - - 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(); - } -} \ No newline at end of file diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ChildTestTypeMethodData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ChildTestTypeMethodData.cs index 79a6ed5..8373033 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ChildTestTypeMethodData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ChildTestTypeMethodData.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -22,4 +22,4 @@ public class ChildTestTypeMethodData : TestTypeWithMethodData return typeof(ChildTestTypeMethodData) .GetMethod(nameof(MultipleValueTest)); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithEmptyTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithEmptyTestData.cs index 276aca2..617aac2 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithEmptyTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithEmptyTestData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -12,4 +12,4 @@ public IEnumerator GetEnumerator() } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithExcessTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithExcessTestData.cs new file mode 100644 index 0000000..352c672 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithExcessTestData.cs @@ -0,0 +1,16 @@ +using System.Collections; + +namespace AutoFixture.TUnit.Tests.TestTypes; + +/// +/// Yields rows with more values than a typical one-parameter test method needs. +/// +public class ClassWithExcessTestData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return ["one", "two", "three"]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithNullTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithNullTestData.cs index e95410f..5cee59c 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithNullTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ClassWithNullTestData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -6,10 +6,10 @@ public class ClassWithNullTestData : IEnumerable { public IEnumerator GetEnumerator() { - yield return null!; - yield return null!; - yield return null!; + yield return null; + yield return null; + yield return null; } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/CompositeTypeWithOverloadedConstructors.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/CompositeTypeWithOverloadedConstructors.cs index b7c8744..f836d09 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/CompositeTypeWithOverloadedConstructors.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/CompositeTypeWithOverloadedConstructors.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; public class CompositeTypeWithOverloadedConstructors { @@ -18,4 +18,4 @@ public CompositeTypeWithOverloadedConstructors(IEnumerable items) } public IEnumerable Items { get; } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/ClassDataShapes.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/ClassDataShapes.cs new file mode 100644 index 0000000..deed7fa --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/ClassDataShapes.cs @@ -0,0 +1,125 @@ +using System.Collections; +using System.Runtime.CompilerServices; +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; + +public class ObjectArrayClassData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return ["hello", 1, new RecordType("world")]; + yield return ["foo", 2, new RecordType("bar")]; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} + +public class StringSequenceClassData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return "alpha"; + yield return "beta"; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} + +public class TupleSequenceClassData : IEnumerable<(string, int)> +{ + public IEnumerator<(string, int)> GetEnumerator() + { + yield return ("a", 1); + yield return ("b", 2); + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} + +public class AsyncObjectArrayClassData : IAsyncEnumerable +{ + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => + EnumerateAsync(cancellationToken).GetAsyncEnumerator(cancellationToken); + + private static async IAsyncEnumerable EnumerateAsync( + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + yield return ["hello", 1, new RecordType("world")]; + yield return ["foo", 2, new RecordType("bar")]; + await Task.CompletedTask; + } +} + +public class AsyncStringSequenceClassData : IAsyncEnumerable +{ + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => + EnumerateAsync(cancellationToken).GetAsyncEnumerator(cancellationToken); + + private static async IAsyncEnumerable EnumerateAsync( + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + yield return "alpha"; + yield return "beta"; + await Task.CompletedTask; + } +} + +public class AsyncTupleSequenceClassData : IAsyncEnumerable<(string, int)> +{ + public IAsyncEnumerator<(string, int)> GetAsyncEnumerator(CancellationToken cancellationToken = default) => + EnumerateAsync(cancellationToken).GetAsyncEnumerator(cancellationToken); + + private static async IAsyncEnumerable<(string, int)> EnumerateAsync( + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + yield return ("a", 1); + yield return ("b", 2); + await Task.CompletedTask; + } +} + +public class EmptyAsyncObjectArrayClassData : IAsyncEnumerable +{ + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => + EnumerateAsync(cancellationToken).GetAsyncEnumerator(cancellationToken); + + private static async IAsyncEnumerable EnumerateAsync( + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + await Task.CompletedTask; + yield break; + } +} + +/// +/// Non-enumerable source type: the constructed instance becomes a single-cell row. +/// +public class StringScalarClassData +{ + public string Value { get; } = "seed"; +} + +/// +/// One row with no columns so AutoClassDataSource fills every constructor parameter. +/// +public class OneEmptyRowClassData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return []; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} + +public class IntSequenceClassData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return 11; + yield return 22; + } + + IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs new file mode 100644 index 0000000..b329df4 --- /dev/null +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DataSourceFixtures/MemberDataShapes.cs @@ -0,0 +1,84 @@ +using TestTypeFoundation; + +namespace AutoFixture.TUnit.Tests.TestTypes.DataSourceFixtures; + +/// +/// Shared member data shapes for public AutoMemberDataSourceAttribute coverage. +/// +public static class MemberDataShapes +{ + public static object? NullValue() => null; + + public static string StringScalar() => "hello"; + + public static object ObjectScalar() => new object(); + + public static (string, int) SingleTuple() => ("a", 1); + + public static IEnumerable EmptyObjectArrays() => []; + + public static IEnumerable ObjectArrays() + { + yield return ["hello", 1, new RecordType("world")]; + yield return ["foo", 2, new RecordType("bar")]; + } + + public static IEnumerable Strings() + { + yield return "one"; + yield return "two"; + } + + public static IEnumerable<(string, int)> Tuples() + { + yield return ("a", 1); + yield return ("b", 2); + } + + public static Task> TaskOfObjectArrays() => + Task.FromResult(ObjectArrays()); + + public static Task> TaskOfTuples() => + Task.FromResult(Tuples()); + + public static async IAsyncEnumerable AsyncObjectArrays() + { + foreach (var row in ObjectArrays()) + { + yield return row; + } + + await Task.CompletedTask; + } + + public static async IAsyncEnumerable AsyncStrings() + { + foreach (var value in Strings()) + { + yield return value; + } + + await Task.CompletedTask; + } + + public static async IAsyncEnumerable<(string, int)> AsyncTuples() + { + foreach (var value in Tuples()) + { + yield return value; + } + + await Task.CompletedTask; + } + + public static async IAsyncEnumerable EmptyAsyncObjectArrays() + { + await Task.CompletedTask; + yield break; + } + + // Field / property mirrors for resolve-member coverage + public static readonly IEnumerable<(string, int)> TupleField = [("a", 1), ("b", 2)]; + + public static IEnumerable<(string, int)> TupleProperty => [("a", 1), ("b", 2)]; +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomization.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomization.cs index d297a7c..e881bb4 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomization.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomization.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; internal class DelegatingCustomization : ICustomization { @@ -13,4 +13,4 @@ public void Customize(IFixture fixture) } internal Action OnCustomize { get; set; } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomizeAttribute.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomizeAttribute.cs index b04bd83..ce33ac8 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomizeAttribute.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingCustomizeAttribute.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -10,4 +10,4 @@ public override ICustomization GetCustomization(ParameterInfo parameter) } public Func OnGetCustomization { get; set; } = p => new DelegatingCustomization(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingDataSource.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingDataSource.cs index 1481b8c..c2e124b 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingDataSource.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingDataSource.cs @@ -4,7 +4,7 @@ namespace AutoFixture.TUnit.Tests.TestTypes; public class DelegatingDataSource : BaseDataSourceAttribute, IDataSource { - public IEnumerable TestData { get; set; } = Array.Empty(); + public IEnumerable TestData { get; set; } = []; public override async IAsyncEnumerable>> GetData(DataGeneratorMetadata dataGeneratorMetadata) { diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingFixture.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingFixture.cs index 1615294..b8da0bd 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingFixture.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingFixture.cs @@ -1,4 +1,4 @@ -using AutoFixture.Dsl; +using AutoFixture.Dsl; using AutoFixture.Kernel; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -91,4 +91,4 @@ public object Create(object request, ISpecimenContext context) internal Func OnCreate { get; set; } = (_, _) => new object(); internal Action OnCustomize { get; set; } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingMemberDataSource.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingMemberDataSource.cs index 7f198ba..2744020 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingMemberDataSource.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingMemberDataSource.cs @@ -1,4 +1,4 @@ -using AutoFixture.TUnit.Internal; +using AutoFixture.TUnit.Internal; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -11,4 +11,4 @@ public DelegatingMemberDataSource(Type type, string name, params object[] argume } public DataSource GetSource() => this.Source; -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingSpecimenBuilder.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingSpecimenBuilder.cs index c5d6e79..5fa763f 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingSpecimenBuilder.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingSpecimenBuilder.cs @@ -1,4 +1,4 @@ -using AutoFixture.Kernel; +using AutoFixture.Kernel; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -10,4 +10,4 @@ public object Create(object request, ISpecimenContext context) } internal Func OnCreate { get; set; } = (_, _) => new object(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingTestData.cs index b8d688b..734a3dc 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DelegatingTestData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -19,4 +19,4 @@ public DelegatingTestData(IEnumerable data) public IEnumerator GetEnumerator() => this.data.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoArgumentsAttribute.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoArgumentsAttribute.cs index 701064d..47d80d1 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoArgumentsAttribute.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoArgumentsAttribute.cs @@ -7,4 +7,4 @@ public DerivedAutoArgumentsAttribute(Func fixtureFactory, params objec : base(fixtureFactory, values) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoClassDataSourceAttribute.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoClassDataSourceAttribute.cs index 92fe044..46d7adc 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoClassDataSourceAttribute.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoClassDataSourceAttribute.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; public class DerivedAutoClassDataSourceAttribute : AutoClassDataSourceAttribute { @@ -11,4 +11,4 @@ public DerivedAutoClassDataSourceAttribute(Func fixtureFactory, Type s : base(fixtureFactory, sourceType, parameters) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoDataSourceAttribute.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoDataSourceAttribute.cs index e8f3dee..ce56eb3 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoDataSourceAttribute.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoDataSourceAttribute.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; public class DerivedAutoDataSourceAttribute : AutoDataSourceAttribute { @@ -6,4 +6,4 @@ public DerivedAutoDataSourceAttribute(Func fixtureFactory) : base(fixtureFactory) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoMemberDataSourceAttribute.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoMemberDataSourceAttribute.cs index 0daf5ec..aa4f170 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoMemberDataSourceAttribute.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/DerivedAutoMemberDataSourceAttribute.cs @@ -1,4 +1,4 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; public class DerivedAutoMemberDataSourceAttribute : AutoMemberDataSourceAttribute { @@ -11,4 +11,4 @@ public DerivedAutoMemberDataSourceAttribute(Func fixtureFactory, Type : base(fixtureFactory, memberType, memberName, parameters) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/EmptyClassData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/EmptyClassData.cs index b9a8f61..1aa8629 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/EmptyClassData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/EmptyClassData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -10,4 +10,4 @@ public IEnumerator GetEnumerator() } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ExampleTestClass.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ExampleTestClass.cs index 8f3b637..e05622e 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ExampleTestClass.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ExampleTestClass.cs @@ -1,12 +1,9 @@ -using System.Diagnostics.CodeAnalysis; using TestTypeFoundation; namespace AutoFixture.TUnit.Tests.TestTypes; public class ExampleTestClass { - [SuppressMessage("Usage", "xUnit1013:Public method should be marked as test", - Justification = "This test method is used through reflection.")] public void TestMethod(int a, string b, EnumType c, Tuple d) { } @@ -14,9 +11,7 @@ public void TestMethod(int a, string b, EnumType c, Tuple d) public class ExampleTestClass { - [SuppressMessage("Usage", "xUnit1013:Public method should be marked as test", - Justification = "This test method is used through reflection.")] public void TestMethod(T1 a, T2 b, T3 c, T4 d) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/FixedParameterBuilder.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/FixedParameterBuilder.cs index 9ef50fc..d066e48 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/FixedParameterBuilder.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/FixedParameterBuilder.cs @@ -9,4 +9,4 @@ public FixedParameterBuilder(string name, T value) : base(new FixedBuilder(value), new ParameterSpecification(typeof(T), name)) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/InlineAttributeTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/InlineAttributeTestData.cs index 3a2533d..fcaf5b2 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/InlineAttributeTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/InlineAttributeTestData.cs @@ -52,4 +52,4 @@ ICustomization CreateCustomization() } public abstract IEnumerable GetData(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/InlineFrozenValuesTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/InlineFrozenValuesTestData.cs index 328be8d..a0e642f 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/InlineFrozenValuesTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/InlineFrozenValuesTestData.cs @@ -32,4 +32,4 @@ internal class InlineFrozenValuesTestData : InlineAttributeTestData<(BaseDataSou TestTypeWithMemberDataSource.GetTestWithFrozenParameter(), ["string_a2", "string_b2", "string_b2"]); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/InlinePrimitiveValuesTestData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/InlinePrimitiveValuesTestData.cs index e77d8ea..1514473 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/InlinePrimitiveValuesTestData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/InlinePrimitiveValuesTestData.cs @@ -35,4 +35,4 @@ internal class InlinePrimitiveValuesTestData : InlineAttributeTestData<(BaseData ["parameter_a3", 13, 332.009m] ); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/MixedTypeClassData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/MixedTypeClassData.cs index e6b2243..26d64a5 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/MixedTypeClassData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/MixedTypeClassData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using TestTypeFoundation; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -15,4 +15,4 @@ public IEnumerator GetEnumerator() } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/MyClass.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/MyClass.cs index c955db3..84695ee 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/MyClass.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/MyClass.cs @@ -1,6 +1,6 @@ -namespace AutoFixture.TUnit.Tests.TestTypes; +namespace AutoFixture.TUnit.Tests.TestTypes; public class MyClass { public T Echo(T item) => item; -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterNameCriterion.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterNameCriterion.cs index 274c65d..fa6b17e 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterNameCriterion.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterNameCriterion.cs @@ -24,4 +24,4 @@ public bool Equals(ParameterInfo other) { return this.NameCriterion.Equals(other.Name); } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterizedClassData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterizedClassData.cs index 59d2452..3eba681 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterizedClassData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/ParameterizedClassData.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using TestTypeFoundation; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -23,4 +23,4 @@ public IEnumerator GetEnumerator() } IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/SampleTestType.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/SampleTestType.cs index 7e5ec85..3bd63ca 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/SampleTestType.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/SampleTestType.cs @@ -1,4 +1,4 @@ -using TestTypeFoundation; +using TestTypeFoundation; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -16,6 +16,10 @@ public void TestMethodWithMultipleParameters(string a, int b, double c) { } + public void TestMethodWithTwoParameters(string a, int b) + { + } + public void TestMethodWithReferenceTypeParameter(string a, int b, PropertyHolder c) { } @@ -35,4 +39,4 @@ public void TestMethodWithCustomizedParameter([Frozen] string a, int b, Property public void TestMethodWithMultipleCustomizations([Frozen] string a, [Frozen] int b, [Greedy][Frozen] PropertyHolder c) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMemberDataSource.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMemberDataSource.cs index 0a145e6..dd66f94 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMemberDataSource.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMemberDataSource.cs @@ -1,12 +1,9 @@ -using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace AutoFixture.TUnit.Tests.TestTypes; internal class TestTypeWithMemberDataSource { - [SuppressMessage("Usage", "xUnit1013:Public method should be marked as test", - Justification = "Test is invoked through reflection.")] public async Task MultipleValueTest(string a, int b, decimal c) { await Assert.That(a).IsNotNull(); @@ -34,4 +31,4 @@ public static MethodInfo GetMultipleValueTestMethodInfo() => public static MethodInfo GetTestWithFrozenParameter() => typeof(TestTypeWithMemberDataSource) .GetMethod(nameof(TestWithFrozenParameter)); -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMethodData.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMethodData.cs index 751998b..c7a2e43 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMethodData.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/TestTypeWithMethodData.cs @@ -156,4 +156,4 @@ public static IEnumerable GetStringValuesTestData() } public static IEnumerable GetEmptyTestData() => []; -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithCustomizationAttributes.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithCustomizationAttributes.cs index e27c00e..b839c7b 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithCustomizationAttributes.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithCustomizationAttributes.cs @@ -1,4 +1,3 @@ -using TestTypeFoundation; using ConcreteType = TestTypeFoundation.ConcreteType; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -52,4 +51,4 @@ public void CreateWithFrozenAndNoAutoProperties([Frozen, NoAutoProperties] Concr public void CreateWithNoAutoPropertiesAndFrozen([NoAutoProperties, Frozen] ConcreteType sut) { } -} \ No newline at end of file +} diff --git a/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithIParameterCustomizationSourceUsage.cs b/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithIParameterCustomizationSourceUsage.cs index 8099949..224523d 100644 --- a/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithIParameterCustomizationSourceUsage.cs +++ b/tests/AutoFixture.TUnit.Tests/TestTypes/TypeWithIParameterCustomizationSourceUsage.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace AutoFixture.TUnit.Tests.TestTypes; @@ -23,4 +23,4 @@ public void Customize(IFixture fixture) { } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/AbstractClassWithPublicConstructor.cs b/tests/TestTypeFoundation/AbstractClassWithPublicConstructor.cs index 1e038eb..47c8cf2 100644 --- a/tests/TestTypeFoundation/AbstractClassWithPublicConstructor.cs +++ b/tests/TestTypeFoundation/AbstractClassWithPublicConstructor.cs @@ -1,5 +1,5 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public abstract class AbstractClassWithPublicConstructor { -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/AbstractGenericType.cs b/tests/TestTypeFoundation/AbstractGenericType.cs index 376b3a1..a3ce742 100644 --- a/tests/TestTypeFoundation/AbstractGenericType.cs +++ b/tests/TestTypeFoundation/AbstractGenericType.cs @@ -8,4 +8,4 @@ protected AbstractGenericType(T value) } public T Value { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/AbstractType.cs b/tests/TestTypeFoundation/AbstractType.cs index ab273cd..7a3016f 100644 --- a/tests/TestTypeFoundation/AbstractType.cs +++ b/tests/TestTypeFoundation/AbstractType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public abstract class AbstractType { @@ -11,4 +11,4 @@ public abstract class AbstractType public virtual object Property4 { get; set; } public object Field1; -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/AbstractTypeWithConstructorWithMultipleParameters.cs b/tests/TestTypeFoundation/AbstractTypeWithConstructorWithMultipleParameters.cs index 1ab088a..087a7af 100644 --- a/tests/TestTypeFoundation/AbstractTypeWithConstructorWithMultipleParameters.cs +++ b/tests/TestTypeFoundation/AbstractTypeWithConstructorWithMultipleParameters.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public abstract class AbstractTypeWithConstructorWithMultipleParameters { @@ -11,4 +11,4 @@ protected AbstractTypeWithConstructorWithMultipleParameters(T1 parameter1, T2 pa public T1 Property1 { get; } public T2 Property2 { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/AbstractTypeWithNonDefaultConstructor.cs b/tests/TestTypeFoundation/AbstractTypeWithNonDefaultConstructor.cs index 17a2342..93839d8 100644 --- a/tests/TestTypeFoundation/AbstractTypeWithNonDefaultConstructor.cs +++ b/tests/TestTypeFoundation/AbstractTypeWithNonDefaultConstructor.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public abstract class AbstractTypeWithNonDefaultConstructor { @@ -10,4 +10,4 @@ protected AbstractTypeWithNonDefaultConstructor(T value) } public T Property { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ActivityScope.cs b/tests/TestTypeFoundation/ActivityScope.cs index 4f34cc0..210b697 100644 --- a/tests/TestTypeFoundation/ActivityScope.cs +++ b/tests/TestTypeFoundation/ActivityScope.cs @@ -42,4 +42,4 @@ public enum ActivityScope : long /// The set all valid scopes. /// All = OnDuty | OffDuty | Standalone | Parent | Child, -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/CollectionHolder.cs b/tests/TestTypeFoundation/CollectionHolder.cs index b0c5432..ae583fc 100644 --- a/tests/TestTypeFoundation/CollectionHolder.cs +++ b/tests/TestTypeFoundation/CollectionHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class CollectionHolder { public ICollection Collection { get; private set; } = new List(); -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/CompositeType.cs b/tests/TestTypeFoundation/CompositeType.cs index 11c503c..458d5cb 100644 --- a/tests/TestTypeFoundation/CompositeType.cs +++ b/tests/TestTypeFoundation/CompositeType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class CompositeType : AbstractType { @@ -13,4 +13,4 @@ public CompositeType(params AbstractType[] types) } public IEnumerable Types { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ConcreteType.cs b/tests/TestTypeFoundation/ConcreteType.cs index 5748a47..06d1bfd 100644 --- a/tests/TestTypeFoundation/ConcreteType.cs +++ b/tests/TestTypeFoundation/ConcreteType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ConcreteType : AbstractType { @@ -35,4 +35,4 @@ public ConcreteType(object obj1, object obj2, object obj3, object obj4) public override object Property4 { get; set; } public object Property5 { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ConcreteTypeWithPrivateParameterlessConstructor.cs b/tests/TestTypeFoundation/ConcreteTypeWithPrivateParameterlessConstructor.cs index c9ce80c..2f84bdd 100644 --- a/tests/TestTypeFoundation/ConcreteTypeWithPrivateParameterlessConstructor.cs +++ b/tests/TestTypeFoundation/ConcreteTypeWithPrivateParameterlessConstructor.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ConcreteTypeWithPrivateParameterlessConstructor { @@ -9,4 +9,4 @@ private ConcreteTypeWithPrivateParameterlessConstructor() public ConcreteTypeWithPrivateParameterlessConstructor(object obj) { } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/DoubleFieldHolder.cs b/tests/TestTypeFoundation/DoubleFieldHolder.cs index ed1cb9c..2767989 100644 --- a/tests/TestTypeFoundation/DoubleFieldHolder.cs +++ b/tests/TestTypeFoundation/DoubleFieldHolder.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class DoubleFieldHolder { public T1 Field1; public T2 Field2; -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/DoubleParameterType.cs b/tests/TestTypeFoundation/DoubleParameterType.cs index 89f5a2a..b64e594 100644 --- a/tests/TestTypeFoundation/DoubleParameterType.cs +++ b/tests/TestTypeFoundation/DoubleParameterType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class DoubleParameterType { @@ -10,4 +10,4 @@ public DoubleParameterType(T1 parameter1, T2 parameter2) public T1 Parameter1 { get; private set; } public T2 Parameter2 { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/DoublePropertyHolder.cs b/tests/TestTypeFoundation/DoublePropertyHolder.cs index 2087e7f..5e8002f 100644 --- a/tests/TestTypeFoundation/DoublePropertyHolder.cs +++ b/tests/TestTypeFoundation/DoublePropertyHolder.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class DoublePropertyHolder { public T1 Property1 { get; set; } public T2 Property2 { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/EmptyEnum.cs b/tests/TestTypeFoundation/EmptyEnum.cs index 224363e..faff840 100644 --- a/tests/TestTypeFoundation/EmptyEnum.cs +++ b/tests/TestTypeFoundation/EmptyEnum.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public enum EmptyEnum { // this must not contain any values -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/EnumType.cs b/tests/TestTypeFoundation/EnumType.cs index 8c64374..7046f9a 100644 --- a/tests/TestTypeFoundation/EnumType.cs +++ b/tests/TestTypeFoundation/EnumType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public enum EnumType { @@ -54,4 +54,4 @@ public enum ULongEnumType : ulong First = 1, Second, Third -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/EqualityResponder.cs b/tests/TestTypeFoundation/EqualityResponder.cs index 35aaab2..d53aa28 100644 --- a/tests/TestTypeFoundation/EqualityResponder.cs +++ b/tests/TestTypeFoundation/EqualityResponder.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class EqualityResponder { @@ -18,4 +18,4 @@ public override int GetHashCode() { return this.equals.GetHashCode(); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/FieldHolder.cs b/tests/TestTypeFoundation/FieldHolder.cs index c3135eb..a3f5c8d 100644 --- a/tests/TestTypeFoundation/FieldHolder.cs +++ b/tests/TestTypeFoundation/FieldHolder.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace TestTypeFoundation; @@ -11,4 +11,4 @@ public static FieldInfo GetField() return typeof(FieldHolder) .GetRuntimeField(nameof(Field)); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GenericType.cs b/tests/TestTypeFoundation/GenericType.cs index 0ccfd52..13e6d4a 100644 --- a/tests/TestTypeFoundation/GenericType.cs +++ b/tests/TestTypeFoundation/GenericType.cs @@ -9,4 +9,4 @@ public GenericType(T value) } private T Value { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedConstructorHost.cs b/tests/TestTypeFoundation/GuardedConstructorHost.cs index 418a627..a13fe3e 100644 --- a/tests/TestTypeFoundation/GuardedConstructorHost.cs +++ b/tests/TestTypeFoundation/GuardedConstructorHost.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class GuardedConstructorHost where T : class @@ -9,4 +9,4 @@ public GuardedConstructorHost(T item) } public T Item { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyField.cs b/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyField.cs index df72d37..3d720ee 100644 --- a/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyField.cs +++ b/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyField.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class GuardedConstructorHostHoldingStaticReadOnlyField where TItem : class @@ -16,4 +16,4 @@ public GuardedConstructorHostHoldingStaticReadOnlyField(TItem item) } public TItem Item { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyProperty.cs b/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyProperty.cs index bd8b30f..60431ac 100644 --- a/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyProperty.cs +++ b/tests/TestTypeFoundation/GuardedConstructorHostHoldingStaticReadOnlyProperty.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class GuardedConstructorHostHoldingStaticReadOnlyProperty where TItem : class @@ -16,4 +16,4 @@ public GuardedConstructorHostHoldingStaticReadOnlyProperty(TItem item) public static TStaticProperty Property { get; private set; } public TItem Item { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedMethodHost.cs b/tests/TestTypeFoundation/GuardedMethodHost.cs index b092444..73f4b40 100644 --- a/tests/TestTypeFoundation/GuardedMethodHost.cs +++ b/tests/TestTypeFoundation/GuardedMethodHost.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class GuardedMethodHost { @@ -77,4 +77,4 @@ public void ConsumeStringAndInt32AndGuid(string s, int i, Guid g) throw new ArgumentException("Guid cannot be empty.", nameof(g)); } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedPropertyHolder.cs b/tests/TestTypeFoundation/GuardedPropertyHolder.cs index 414d503..59abeee 100644 --- a/tests/TestTypeFoundation/GuardedPropertyHolder.cs +++ b/tests/TestTypeFoundation/GuardedPropertyHolder.cs @@ -10,4 +10,4 @@ public T Property get => this.property; set => this.property = value ?? throw new ArgumentNullException(nameof(value)); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/GuardedStaticMethodOnStaticTypeHost.cs b/tests/TestTypeFoundation/GuardedStaticMethodOnStaticTypeHost.cs index 1b9afba..7da6515 100644 --- a/tests/TestTypeFoundation/GuardedStaticMethodOnStaticTypeHost.cs +++ b/tests/TestTypeFoundation/GuardedStaticMethodOnStaticTypeHost.cs @@ -6,4 +6,4 @@ public static void Method(object argument) { if (argument is null) throw new ArgumentNullException(nameof(argument)); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/IInterface.cs b/tests/TestTypeFoundation/IInterface.cs index e3377b0..3e390b6 100644 --- a/tests/TestTypeFoundation/IInterface.cs +++ b/tests/TestTypeFoundation/IInterface.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public interface IInterface { object MakeIt(object obj); -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/IllBehavedPropertyHolder.cs b/tests/TestTypeFoundation/IllBehavedPropertyHolder.cs index 63a9bd2..a5867f7 100644 --- a/tests/TestTypeFoundation/IllBehavedPropertyHolder.cs +++ b/tests/TestTypeFoundation/IllBehavedPropertyHolder.cs @@ -28,4 +28,4 @@ public T PropertyIllBehavedSet this.propertyIllBehavedSet = default(T); } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/IndexedPropertyHolder.cs b/tests/TestTypeFoundation/IndexedPropertyHolder.cs index 45f6adf..6ae35d4 100644 --- a/tests/TestTypeFoundation/IndexedPropertyHolder.cs +++ b/tests/TestTypeFoundation/IndexedPropertyHolder.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class IndexedPropertyHolder { @@ -11,4 +11,4 @@ public T this[int index] get { return this.items[index]; } set { this.items[index] = value; } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/InternalGetterPropertyHolder.cs b/tests/TestTypeFoundation/InternalGetterPropertyHolder.cs index 04e5283..4638ea6 100644 --- a/tests/TestTypeFoundation/InternalGetterPropertyHolder.cs +++ b/tests/TestTypeFoundation/InternalGetterPropertyHolder.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class InternalGetterPropertyHolder { @@ -8,4 +8,4 @@ public InternalGetterPropertyHolder(T property) } public T Property { internal get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ItemContainer.cs b/tests/TestTypeFoundation/ItemContainer.cs index 77395dd..10851fa 100644 --- a/tests/TestTypeFoundation/ItemContainer.cs +++ b/tests/TestTypeFoundation/ItemContainer.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ItemContainer { @@ -18,4 +18,4 @@ public ItemContainer(params T[] items) } public IEnumerable Items { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ItemHolder.cs b/tests/TestTypeFoundation/ItemHolder.cs index 709e202..ea7a55e 100644 --- a/tests/TestTypeFoundation/ItemHolder.cs +++ b/tests/TestTypeFoundation/ItemHolder.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ItemHolder { @@ -59,4 +59,4 @@ private ItemHolder(T[] items) } public IEnumerable Items { get; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/MultiUnorderedConstructorType.cs b/tests/TestTypeFoundation/MultiUnorderedConstructorType.cs index 6c299aa..fc769d4 100644 --- a/tests/TestTypeFoundation/MultiUnorderedConstructorType.cs +++ b/tests/TestTypeFoundation/MultiUnorderedConstructorType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class MultiUnorderedConstructorType { @@ -34,4 +34,4 @@ public ParameterObject(string text, int number) public int Number { get; } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/MutableValueType.cs b/tests/TestTypeFoundation/MutableValueType.cs index 724247c..ea47bae 100644 --- a/tests/TestTypeFoundation/MutableValueType.cs +++ b/tests/TestTypeFoundation/MutableValueType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public struct MutableValueType { @@ -12,4 +12,4 @@ public MutableValueType(object property1, object property2, object property3) public object Property1 { get; set; } public object Property2 { get; set; } public object Property3 { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/MutableValueTypeWithoutConstructor.cs b/tests/TestTypeFoundation/MutableValueTypeWithoutConstructor.cs index 158d1a3..0ae7efd 100644 --- a/tests/TestTypeFoundation/MutableValueTypeWithoutConstructor.cs +++ b/tests/TestTypeFoundation/MutableValueTypeWithoutConstructor.cs @@ -1,7 +1,7 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public struct MutableValueTypeWithoutConstructor { public object Property1 { get; set; } public object Property2 { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/NonCompliantCollectionHolder.cs b/tests/TestTypeFoundation/NonCompliantCollectionHolder.cs index 00205a8..256d5f2 100644 --- a/tests/TestTypeFoundation/NonCompliantCollectionHolder.cs +++ b/tests/TestTypeFoundation/NonCompliantCollectionHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class NonCompliantCollectionHolder { public ICollection Collection { get; set; } = new List(); -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/NoopInterfaceImplementer.cs b/tests/TestTypeFoundation/NoopInterfaceImplementer.cs index b99cd27..97aad50 100644 --- a/tests/TestTypeFoundation/NoopInterfaceImplementer.cs +++ b/tests/TestTypeFoundation/NoopInterfaceImplementer.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class NoopInterfaceImplementer : IInterface { @@ -6,4 +6,4 @@ public object MakeIt(object obj) { return obj; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/Properties/AssemblyInfo.cs b/tests/TestTypeFoundation/Properties/AssemblyInfo.cs index 1d950fa..024d383 100644 --- a/tests/TestTypeFoundation/Properties/AssemblyInfo.cs +++ b/tests/TestTypeFoundation/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using System.Runtime.InteropServices; [assembly: AssemblyCulture("")] diff --git a/tests/TestTypeFoundation/PropertyHolder.cs b/tests/TestTypeFoundation/PropertyHolder.cs index b1e471c..5550f71 100644 --- a/tests/TestTypeFoundation/PropertyHolder.cs +++ b/tests/TestTypeFoundation/PropertyHolder.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace TestTypeFoundation; @@ -16,4 +16,4 @@ public static PropertyInfo GetProperty() return typeof(PropertyHolder) .GetRuntimeProperty(nameof(Property)); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/QuadrupleParameterType.cs b/tests/TestTypeFoundation/QuadrupleParameterType.cs index ccb9147..cb450b5 100644 --- a/tests/TestTypeFoundation/QuadrupleParameterType.cs +++ b/tests/TestTypeFoundation/QuadrupleParameterType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class QuadrupleParameterType { @@ -14,4 +14,4 @@ public QuadrupleParameterType(T1 parameter1, T2 parameter2, T3 parameter3, T4 pa public T2 Parameter2 { get; private set; } public T3 Parameter3 { get; private set; } public T4 Parameter4 { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ReadOnlyFieldHolder.cs b/tests/TestTypeFoundation/ReadOnlyFieldHolder.cs index 30250c9..6ce2d76 100644 --- a/tests/TestTypeFoundation/ReadOnlyFieldHolder.cs +++ b/tests/TestTypeFoundation/ReadOnlyFieldHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ReadOnlyFieldHolder { public readonly T Field; -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/ReadOnlyPropertyHolder.cs b/tests/TestTypeFoundation/ReadOnlyPropertyHolder.cs index 392624a..3651266 100644 --- a/tests/TestTypeFoundation/ReadOnlyPropertyHolder.cs +++ b/tests/TestTypeFoundation/ReadOnlyPropertyHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class ReadOnlyPropertyHolder { public T Property { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/RecordType.cs b/tests/TestTypeFoundation/RecordType.cs index 7ad88cd..5aa7691 100644 --- a/tests/TestTypeFoundation/RecordType.cs +++ b/tests/TestTypeFoundation/RecordType.cs @@ -33,4 +33,4 @@ public override int GetHashCode() { return EqualityComparer.Default.GetHashCode(this.Value); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/SingleParameterType.cs b/tests/TestTypeFoundation/SingleParameterType.cs index e157947..1928e57 100644 --- a/tests/TestTypeFoundation/SingleParameterType.cs +++ b/tests/TestTypeFoundation/SingleParameterType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class SingleParameterType { @@ -8,4 +8,4 @@ public SingleParameterType(T parameter) } public T Parameter { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/StaticFieldHolder.cs b/tests/TestTypeFoundation/StaticFieldHolder.cs index 738e055..af50e43 100644 --- a/tests/TestTypeFoundation/StaticFieldHolder.cs +++ b/tests/TestTypeFoundation/StaticFieldHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class StaticFieldHolder { public static T Field; -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/StaticPropertyHolder.cs b/tests/TestTypeFoundation/StaticPropertyHolder.cs index d95b0f7..e57d00f 100644 --- a/tests/TestTypeFoundation/StaticPropertyHolder.cs +++ b/tests/TestTypeFoundation/StaticPropertyHolder.cs @@ -1,6 +1,6 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class StaticPropertyHolder { public static T Property { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TestTypeFoundation.csproj b/tests/TestTypeFoundation/TestTypeFoundation.csproj index 3c758eb..87bb41a 100644 --- a/tests/TestTypeFoundation/TestTypeFoundation.csproj +++ b/tests/TestTypeFoundation/TestTypeFoundation.csproj @@ -1,19 +1,20 @@  - netstandard2.0 TestTypeFoundation TestTypeFoundation disable + false false - true + false + + false - - + diff --git a/tests/TestTypeFoundation/TriState.cs b/tests/TestTypeFoundation/TriState.cs index c88423c..5f3fadd 100644 --- a/tests/TestTypeFoundation/TriState.cs +++ b/tests/TestTypeFoundation/TriState.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public enum TriState { First = 0, Second, Third -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TripleParameterType.cs b/tests/TestTypeFoundation/TripleParameterType.cs index 952e515..56f874f 100644 --- a/tests/TestTypeFoundation/TripleParameterType.cs +++ b/tests/TestTypeFoundation/TripleParameterType.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TripleParameterType { @@ -12,4 +12,4 @@ public TripleParameterType(T1 parameter1, T2 parameter2, T3 parameter3) public T1 Parameter1 { get; private set; } public T2 Parameter2 { get; private set; } public T3 Parameter3 { get; private set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TriplePropertyHolder.cs b/tests/TestTypeFoundation/TriplePropertyHolder.cs index f9ec32a..2e6c720 100644 --- a/tests/TestTypeFoundation/TriplePropertyHolder.cs +++ b/tests/TestTypeFoundation/TriplePropertyHolder.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TriplePropertyHolder { @@ -7,4 +7,4 @@ public class TriplePropertyHolder public T2 Property2 { get; set; } public T3 Property3 { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithCastOperatorsWithoutPublicConstructor.cs b/tests/TestTypeFoundation/TypeWithCastOperatorsWithoutPublicConstructor.cs index 300d37c..baeba21 100644 --- a/tests/TestTypeFoundation/TypeWithCastOperatorsWithoutPublicConstructor.cs +++ b/tests/TestTypeFoundation/TypeWithCastOperatorsWithoutPublicConstructor.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithCastOperatorsWithoutPublicConstructor { @@ -15,4 +15,4 @@ public static explicit operator TypeWithCastOperatorsWithoutPublicConstructor(st { return new TypeWithCastOperatorsWithoutPublicConstructor(); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithConcreteParameterMethod.cs b/tests/TestTypeFoundation/TypeWithConcreteParameterMethod.cs index 0007af5..b6facde 100644 --- a/tests/TestTypeFoundation/TypeWithConcreteParameterMethod.cs +++ b/tests/TestTypeFoundation/TypeWithConcreteParameterMethod.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithConcreteParameterMethod { public void DoSomething(ConcreteType param) { } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithEmptyEnumField.cs b/tests/TestTypeFoundation/TypeWithEmptyEnumField.cs index 4fcdd3c..1773fc5 100644 --- a/tests/TestTypeFoundation/TypeWithEmptyEnumField.cs +++ b/tests/TestTypeFoundation/TypeWithEmptyEnumField.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithEmptyEnumField { public EmptyEnum EmptyEnumField; public EmptyEnum EmptyEnumProperty { get; set; } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithFactoryMethod.cs b/tests/TestTypeFoundation/TypeWithFactoryMethod.cs index 6921237..560d764 100644 --- a/tests/TestTypeFoundation/TypeWithFactoryMethod.cs +++ b/tests/TestTypeFoundation/TypeWithFactoryMethod.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithFactoryMethod { @@ -20,4 +20,4 @@ public static TypeWithFactoryMethod Create(IEnumerable arguments) { return new TypeWithFactoryMethod(); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithFactoryProperty.cs b/tests/TestTypeFoundation/TypeWithFactoryProperty.cs index 8355290..8b784f4 100644 --- a/tests/TestTypeFoundation/TypeWithFactoryProperty.cs +++ b/tests/TestTypeFoundation/TypeWithFactoryProperty.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithFactoryProperty { @@ -13,4 +13,4 @@ public static TypeWithFactoryProperty Factory return new TypeWithFactoryProperty(); } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithIndexer.cs b/tests/TestTypeFoundation/TypeWithIndexer.cs index e5b7c0f..3552e4f 100644 --- a/tests/TestTypeFoundation/TypeWithIndexer.cs +++ b/tests/TestTypeFoundation/TypeWithIndexer.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithIndexer { @@ -15,4 +15,4 @@ public string this[string index] this.dict[index] = value; } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithOverloadedMembers.cs b/tests/TestTypeFoundation/TypeWithOverloadedMembers.cs index 7751e05..b9f2d32 100644 --- a/tests/TestTypeFoundation/TypeWithOverloadedMembers.cs +++ b/tests/TestTypeFoundation/TypeWithOverloadedMembers.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace TestTypeFoundation; @@ -25,4 +25,4 @@ public void DoSomething(object x, object y, object z) public static MethodInfo GetDoSomethingMethod(params Type[] parameterTypes) => typeof(TypeWithOverloadedMembers) .GetMethod(nameof(DoSomething), parameterTypes); -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithPseudoFactoryMethod.cs b/tests/TestTypeFoundation/TypeWithPseudoFactoryMethod.cs index 695353f..62d2210 100644 --- a/tests/TestTypeFoundation/TypeWithPseudoFactoryMethod.cs +++ b/tests/TestTypeFoundation/TypeWithPseudoFactoryMethod.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; /// /// This type contains a method that returns an instance of the same type @@ -17,4 +17,4 @@ public static TypeWithPseudoFactoryMethod DoSomething( { return new TypeWithPseudoFactoryMethod(); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/TypeWithRefMethod.cs b/tests/TestTypeFoundation/TypeWithRefMethod.cs index e709a7e..8dbc85d 100644 --- a/tests/TestTypeFoundation/TypeWithRefMethod.cs +++ b/tests/TestTypeFoundation/TypeWithRefMethod.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class TypeWithRefMethod { @@ -7,4 +7,4 @@ public void InvokeIt(T x, ref T y) if (x is null) throw new ArgumentNullException(nameof(x)); if (y is null) throw new ArgumentNullException(nameof(y)); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/UnguardedConstructorHost.cs b/tests/TestTypeFoundation/UnguardedConstructorHost.cs index 5ae0dc6..40239a9 100644 --- a/tests/TestTypeFoundation/UnguardedConstructorHost.cs +++ b/tests/TestTypeFoundation/UnguardedConstructorHost.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; namespace TestTypeFoundation; @@ -23,4 +23,4 @@ public static ParameterInfo GetParameter() { return GetConstructor().GetParameters().Single(); } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/UnguardedMethodHost.cs b/tests/TestTypeFoundation/UnguardedMethodHost.cs index 6e06bb3..4b38407 100644 --- a/tests/TestTypeFoundation/UnguardedMethodHost.cs +++ b/tests/TestTypeFoundation/UnguardedMethodHost.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public class UnguardedMethodHost { @@ -13,4 +13,4 @@ public void ConsumeGuardedGuidAndUnguardedString(Guid g, string s) throw new ArgumentException("Guid cannot be empty.", nameof(g)); } } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/UnguardedStaticMethodOnStaticTypeHost.cs b/tests/TestTypeFoundation/UnguardedStaticMethodOnStaticTypeHost.cs index 338390c..0fd555a 100644 --- a/tests/TestTypeFoundation/UnguardedStaticMethodOnStaticTypeHost.cs +++ b/tests/TestTypeFoundation/UnguardedStaticMethodOnStaticTypeHost.cs @@ -1,8 +1,8 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public static class UnguardedStaticMethodOnStaticTypeHost { public static void Method(object argument) { } -} \ No newline at end of file +} diff --git a/tests/TestTypeFoundation/UnguardedStaticPropertyOnStaticTypeHost.cs b/tests/TestTypeFoundation/UnguardedStaticPropertyOnStaticTypeHost.cs index 92c1dfe..fcc7126 100644 --- a/tests/TestTypeFoundation/UnguardedStaticPropertyOnStaticTypeHost.cs +++ b/tests/TestTypeFoundation/UnguardedStaticPropertyOnStaticTypeHost.cs @@ -1,4 +1,4 @@ -namespace TestTypeFoundation; +namespace TestTypeFoundation; public static class UnguardedStaticPropertyOnStaticTypeHost { @@ -7,4 +7,4 @@ public static object Property get; set; } -} \ No newline at end of file +}