├── .gitignore ├── Simple.sln ├── lib ├── powerassert.zip └── powerassert │ └── powerassert │ ├── .hg_archival.txt │ ├── .hgignore │ ├── .hgtags │ ├── PowerAssert.sln │ ├── PowerAssert │ ├── Annotations.cs │ ├── Extensions.cs │ ├── Infrastructure │ │ ├── ExpressionParser.cs │ │ ├── NaturalExpressionProcessor.cs │ │ ├── NodeFormatter.cs │ │ ├── Nodes │ │ │ ├── ArrayIndexNode.cs │ │ │ ├── BinaryNode.cs │ │ │ ├── ConditionalNode.cs │ │ │ ├── ConstantNode.cs │ │ │ ├── MemberAccessNode.cs │ │ │ ├── MethodCallNode.cs │ │ │ ├── NewArrayNode.cs │ │ │ ├── Node.cs │ │ │ └── UnaryNode.cs │ │ ├── Util.Generated.cs │ │ └── Util.tt │ ├── PAssert.cs │ ├── PowerAssertForked.csproj │ └── Properties │ │ └── AssemblyInfo.cs │ ├── PowerAssertTests │ ├── EndToEndTest.cs │ ├── NodeFormatterTest.cs │ ├── ParserTest.cs │ ├── PowerAssertTests.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ └── ThrowsTest.cs │ └── lib │ └── nunit.framework.dll └── src ├── DocGeneratorExample ├── AccountSpecifications.cs ├── DocGeneratorExample.csproj ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── app.config ├── Simple.Testing.CientFramework ├── Simple.Testing.ClientFramework.csproj └── SpecificationTemplates.cs ├── Simple.Testing.ClientFramework ├── Properties │ └── AssemblyInfo.cs ├── Simple.Testing.ClientFramework.csproj └── SpecificationTemplates.cs ├── Simple.Testing.Example ├── DataDrivenSpecification.cs ├── FailingSpecification.cs ├── Properties │ └── AssemblyInfo.cs ├── QuerySpecification.cs ├── Simple.Testing.Example.csproj └── SutSpecification.cs ├── Simple.Testing.Framework.Tests ├── MightyMooseIgnoreAttribute.cs ├── NamedMethodGeneratorTests.cs ├── PartialApplicationVisitorSpecifications.cs ├── PassingSpecification.cs ├── Properties │ └── AssemblyInfo.cs ├── Simple.Testing.Framework.Tests.csproj └── SpecificationRunnerSpecifications.cs ├── Simple.Testing.Framework ├── ISpecificationGenerator.cs ├── NamedMethodsGenerator.cs ├── OnTypeGenerator.cs ├── PartialApplyicationVisitor.cs ├── Properties │ └── AssemblyInfo.cs ├── RootGenerator.cs ├── RunResult.cs ├── Simple.Testing.Framework.csproj ├── SimpleRunner.cs ├── SpecificationRunner.cs ├── SpecificationToRun.cs ├── TypeReader.cs └── extensions.cs └── Simple.Testing.Runner ├── Options.cs ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── Simple.Testing.Runner.csproj └── app.config /.gitignore: -------------------------------------------------------------------------------- 1 | obj 2 | bin 3 | deploy 4 | deploy/* 5 | test-results/ 6 | _ReSharper.* 7 | *.csproj.user 8 | *.resharper.user 9 | *.resharper 10 | *.suo 11 | *.cache 12 | *.userprefs 13 | *.pidb 14 | SolutionVersion.cs 15 | lib/MoMA/Reports/submit.xml 16 | build_output 17 | ReleaseBinaries 18 | code_drop 19 | TestResult.xml 20 | openlocal.sh 21 | openlocal.bat 22 | ~$* 23 | Debug/ 24 | Release/ 25 | AutoTest.VS.xml 26 | ldeploy.bat 27 | *_mm_cache.bin 28 | *.ncrunchsolution 29 | *.ncrunchsolution.user 30 | *~ 31 | -------------------------------------------------------------------------------- /Simple.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Simple.Testing.Framework", "src\Simple.Testing.Framework\Simple.Testing.Framework.csproj", "{A6E67E2A-2A26-4016-BE26-D6F3141729D9}" 5 | EndProject 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{F4BD98A7-2250-4BD0-AAC5-4F4566E85D31}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocGeneratorExample", "src\DocGeneratorExample\DocGeneratorExample.csproj", "{60800BA0-9F82-4CE4-A283-5BC27CC7DE04}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Simple.Testing.Example", "src\Simple.Testing.Example\Simple.Testing.Example.csproj", "{A245A823-1DA4-4086-A265-158DC379B446}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Simple.Testing.Framework.Tests", "src\Simple.Testing.Framework.Tests\Simple.Testing.Framework.Tests.csproj", "{25DA7F29-6653-40AA-BB99-35D4BDB840B0}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Simple.Testing.Runner", "src\Simple.Testing.Runner\Simple.Testing.Runner.csproj", "{415B71AE-58D4-4DC3-AD50-6E816DB647A2}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Simple.Testing.ClientFramework", "src\Simple.Testing.ClientFramework\Simple.Testing.ClientFramework.csproj", "{AFE5EA9F-2829-4D63-9850-34803552C793}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerAssertForked", "lib\powerassert\powerassert\PowerAssert\PowerAssertForked.csproj", "{7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Debug|Mixed Platforms = Debug|Mixed Platforms 24 | Debug|x86 = Debug|x86 25 | NuPackRelease|Any CPU = NuPackRelease|Any CPU 26 | NuPackRelease|Mixed Platforms = NuPackRelease|Mixed Platforms 27 | NuPackRelease|x86 = NuPackRelease|x86 28 | Release|Any CPU = Release|Any CPU 29 | Release|Mixed Platforms = Release|Mixed Platforms 30 | Release|x86 = Release|x86 31 | EndGlobalSection 32 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 33 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 36 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 37 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.Debug|x86.ActiveCfg = Debug|Any CPU 38 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.NuPackRelease|Any CPU.ActiveCfg = Release|Any CPU 39 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.NuPackRelease|Any CPU.Build.0 = Release|Any CPU 40 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.NuPackRelease|Mixed Platforms.ActiveCfg = Release|Any CPU 41 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.NuPackRelease|Mixed Platforms.Build.0 = Release|Any CPU 42 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.NuPackRelease|x86.ActiveCfg = Release|Any CPU 43 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.Release|Any CPU.Build.0 = Release|Any CPU 45 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 46 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.Release|Mixed Platforms.Build.0 = Release|Any CPU 47 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9}.Release|x86.ActiveCfg = Release|Any CPU 48 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.Debug|Any CPU.ActiveCfg = Debug|x86 49 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 50 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.Debug|Mixed Platforms.Build.0 = Debug|x86 51 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.Debug|x86.ActiveCfg = Debug|x86 52 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.Debug|x86.Build.0 = Debug|x86 53 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.NuPackRelease|Any CPU.ActiveCfg = Release|x86 54 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.NuPackRelease|Mixed Platforms.ActiveCfg = Release|x86 55 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.NuPackRelease|Mixed Platforms.Build.0 = Release|x86 56 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.NuPackRelease|x86.ActiveCfg = Release|x86 57 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.NuPackRelease|x86.Build.0 = Release|x86 58 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.Release|Any CPU.ActiveCfg = Release|x86 59 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.Release|Mixed Platforms.ActiveCfg = Release|x86 60 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.Release|Mixed Platforms.Build.0 = Release|x86 61 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.Release|x86.ActiveCfg = Release|x86 62 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04}.Release|x86.Build.0 = Release|x86 63 | {A245A823-1DA4-4086-A265-158DC379B446}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 64 | {A245A823-1DA4-4086-A265-158DC379B446}.Debug|Any CPU.Build.0 = Debug|Any CPU 65 | {A245A823-1DA4-4086-A265-158DC379B446}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 66 | {A245A823-1DA4-4086-A265-158DC379B446}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 67 | {A245A823-1DA4-4086-A265-158DC379B446}.Debug|x86.ActiveCfg = Debug|Any CPU 68 | {A245A823-1DA4-4086-A265-158DC379B446}.NuPackRelease|Any CPU.ActiveCfg = Release|Any CPU 69 | {A245A823-1DA4-4086-A265-158DC379B446}.NuPackRelease|Any CPU.Build.0 = Release|Any CPU 70 | {A245A823-1DA4-4086-A265-158DC379B446}.NuPackRelease|Mixed Platforms.ActiveCfg = Release|Any CPU 71 | {A245A823-1DA4-4086-A265-158DC379B446}.NuPackRelease|Mixed Platforms.Build.0 = Release|Any CPU 72 | {A245A823-1DA4-4086-A265-158DC379B446}.NuPackRelease|x86.ActiveCfg = Release|Any CPU 73 | {A245A823-1DA4-4086-A265-158DC379B446}.Release|Any CPU.ActiveCfg = Release|Any CPU 74 | {A245A823-1DA4-4086-A265-158DC379B446}.Release|Any CPU.Build.0 = Release|Any CPU 75 | {A245A823-1DA4-4086-A265-158DC379B446}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 76 | {A245A823-1DA4-4086-A265-158DC379B446}.Release|Mixed Platforms.Build.0 = Release|Any CPU 77 | {A245A823-1DA4-4086-A265-158DC379B446}.Release|x86.ActiveCfg = Release|Any CPU 78 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 79 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.Debug|Any CPU.Build.0 = Debug|Any CPU 80 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 81 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 82 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.Debug|x86.ActiveCfg = Debug|Any CPU 83 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.NuPackRelease|Any CPU.ActiveCfg = Release|Any CPU 84 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.NuPackRelease|Any CPU.Build.0 = Release|Any CPU 85 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.NuPackRelease|Mixed Platforms.ActiveCfg = Release|Any CPU 86 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.NuPackRelease|Mixed Platforms.Build.0 = Release|Any CPU 87 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.NuPackRelease|x86.ActiveCfg = Release|Any CPU 88 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.Release|Any CPU.ActiveCfg = Release|Any CPU 89 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.Release|Any CPU.Build.0 = Release|Any CPU 90 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 91 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.Release|Mixed Platforms.Build.0 = Release|Any CPU 92 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0}.Release|x86.ActiveCfg = Release|Any CPU 93 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.Debug|Any CPU.ActiveCfg = Debug|x86 94 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 95 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.Debug|Mixed Platforms.Build.0 = Debug|x86 96 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.Debug|x86.ActiveCfg = Debug|x86 97 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.Debug|x86.Build.0 = Debug|x86 98 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.NuPackRelease|Any CPU.ActiveCfg = Release|x86 99 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.NuPackRelease|Mixed Platforms.ActiveCfg = Release|x86 100 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.NuPackRelease|Mixed Platforms.Build.0 = Release|x86 101 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.NuPackRelease|x86.ActiveCfg = Release|x86 102 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.NuPackRelease|x86.Build.0 = Release|x86 103 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.Release|Any CPU.ActiveCfg = Release|x86 104 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.Release|Mixed Platforms.ActiveCfg = Release|x86 105 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.Release|Mixed Platforms.Build.0 = Release|x86 106 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.Release|x86.ActiveCfg = Release|x86 107 | {415B71AE-58D4-4DC3-AD50-6E816DB647A2}.Release|x86.Build.0 = Release|x86 108 | {AFE5EA9F-2829-4D63-9850-34803552C793}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 109 | {AFE5EA9F-2829-4D63-9850-34803552C793}.Debug|Any CPU.Build.0 = Debug|Any CPU 110 | {AFE5EA9F-2829-4D63-9850-34803552C793}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 111 | {AFE5EA9F-2829-4D63-9850-34803552C793}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 112 | {AFE5EA9F-2829-4D63-9850-34803552C793}.Debug|x86.ActiveCfg = Debug|Any CPU 113 | {AFE5EA9F-2829-4D63-9850-34803552C793}.NuPackRelease|Any CPU.ActiveCfg = Release|Any CPU 114 | {AFE5EA9F-2829-4D63-9850-34803552C793}.NuPackRelease|Any CPU.Build.0 = Release|Any CPU 115 | {AFE5EA9F-2829-4D63-9850-34803552C793}.NuPackRelease|Mixed Platforms.ActiveCfg = Release|Any CPU 116 | {AFE5EA9F-2829-4D63-9850-34803552C793}.NuPackRelease|Mixed Platforms.Build.0 = Release|Any CPU 117 | {AFE5EA9F-2829-4D63-9850-34803552C793}.NuPackRelease|x86.ActiveCfg = Release|Any CPU 118 | {AFE5EA9F-2829-4D63-9850-34803552C793}.Release|Any CPU.ActiveCfg = Release|Any CPU 119 | {AFE5EA9F-2829-4D63-9850-34803552C793}.Release|Any CPU.Build.0 = Release|Any CPU 120 | {AFE5EA9F-2829-4D63-9850-34803552C793}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 121 | {AFE5EA9F-2829-4D63-9850-34803552C793}.Release|Mixed Platforms.Build.0 = Release|Any CPU 122 | {AFE5EA9F-2829-4D63-9850-34803552C793}.Release|x86.ActiveCfg = Release|Any CPU 123 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 124 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Debug|Any CPU.Build.0 = Debug|Any CPU 125 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 126 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 127 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Debug|x86.ActiveCfg = Debug|Any CPU 128 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.NuPackRelease|Any CPU.ActiveCfg = NuPackRelease|Any CPU 129 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.NuPackRelease|Any CPU.Build.0 = NuPackRelease|Any CPU 130 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.NuPackRelease|Mixed Platforms.ActiveCfg = NuPackRelease|Any CPU 131 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.NuPackRelease|Mixed Platforms.Build.0 = NuPackRelease|Any CPU 132 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.NuPackRelease|x86.ActiveCfg = NuPackRelease|Any CPU 133 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Release|Any CPU.ActiveCfg = Release|Any CPU 134 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Release|Any CPU.Build.0 = Release|Any CPU 135 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 136 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Release|Mixed Platforms.Build.0 = Release|Any CPU 137 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Release|x86.ActiveCfg = Release|Any CPU 138 | EndGlobalSection 139 | GlobalSection(SolutionProperties) = preSolution 140 | HideSolutionNode = FALSE 141 | EndGlobalSection 142 | GlobalSection(NestedProjects) = preSolution 143 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04} = {F4BD98A7-2250-4BD0-AAC5-4F4566E85D31} 144 | {A245A823-1DA4-4086-A265-158DC379B446} = {F4BD98A7-2250-4BD0-AAC5-4F4566E85D31} 145 | EndGlobalSection 146 | EndGlobal 147 | -------------------------------------------------------------------------------- /lib/powerassert.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregoryyoung/Simple.Testing/80e8cb06dc19d6d08c7ee9c48ba4a91c77d0c52a/lib/powerassert.zip -------------------------------------------------------------------------------- /lib/powerassert/powerassert/.hg_archival.txt: -------------------------------------------------------------------------------- 1 | repo: 2c8ea7745a23d74598bea917327266eada703926 2 | node: 8e1d4d6874e16f7b2f925a23a19005a26bc386de 3 | branch: default 4 | latesttag: Release 1.0.2 5 | latesttagdistance: 2 6 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/.hgignore: -------------------------------------------------------------------------------- 1 | glob:*.user 2 | glob:*/bin 3 | glob:*/obj 4 | glob:_* 5 | glob:*.suo 6 | glob:PowerAssert/release/lib 7 | glob:*.nupkg 8 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/.hgtags: -------------------------------------------------------------------------------- 1 | 4d81d40701f2d8cf150917e79a64acd47339d6c5 Release 1.0 2 | 8ac20fe95c6598e3407e1aa4bbdbd4aeb0320d57 Release 1.0.1 3 | c6fcc7fc78f36207f75861062f8cae9c8dc4659c Release 1.0.2 4 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerAssert", "PowerAssert\PowerAssert.csproj", "{7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerAssertTests", "PowerAssertTests\PowerAssertTests.csproj", "{665FDD28-99EF-4038-9469-1B27F778BF1D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | NuPackRelease|Any CPU = NuPackRelease|Any CPU 12 | Release|Any CPU = Release|Any CPU 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 16 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Debug|Any CPU.Build.0 = Debug|Any CPU 17 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.NuPackRelease|Any CPU.ActiveCfg = NuPackRelease|Any CPU 18 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.NuPackRelease|Any CPU.Build.0 = NuPackRelease|Any CPU 19 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Release|Any CPU.ActiveCfg = Release|Any CPU 20 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9}.Release|Any CPU.Build.0 = Release|Any CPU 21 | {665FDD28-99EF-4038-9469-1B27F778BF1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {665FDD28-99EF-4038-9469-1B27F778BF1D}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {665FDD28-99EF-4038-9469-1B27F778BF1D}.NuPackRelease|Any CPU.ActiveCfg = Release|Any CPU 24 | {665FDD28-99EF-4038-9469-1B27F778BF1D}.NuPackRelease|Any CPU.Build.0 = Release|Any CPU 25 | {665FDD28-99EF-4038-9469-1B27F778BF1D}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {665FDD28-99EF-4038-9469-1B27F778BF1D}.Release|Any CPU.Build.0 = Release|Any CPU 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Annotations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace JetBrains.Annotations 5 | { 6 | /// 7 | /// Indicates that marked element should be localized or not. 8 | /// 9 | [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)] 10 | internal sealed class LocalizationRequiredAttribute : Attribute 11 | { 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | /// true if a element should be localized; otherwise, false. 16 | internal LocalizationRequiredAttribute(bool required) 17 | { 18 | Required = required; 19 | } 20 | 21 | /// 22 | /// Gets a value indicating whether a element should be localized. 23 | /// true if a element should be localized; otherwise, false. 24 | /// 25 | internal bool Required { get; set; } 26 | 27 | /// 28 | /// Returns whether the value of the given object is equal to the current . 29 | /// 30 | /// The object to test the value equality of. 31 | /// 32 | /// true if the value of the given object is equal to that of the current; otherwise, false. 33 | /// 34 | public override bool Equals(object obj) 35 | { 36 | var attribute = obj as LocalizationRequiredAttribute; 37 | return attribute != null && attribute.Required == Required; 38 | } 39 | 40 | /// 41 | /// Returns the hash code for this instance. 42 | /// 43 | /// A hash code for the current . 44 | public override int GetHashCode() 45 | { 46 | return base.GetHashCode(); 47 | } 48 | } 49 | 50 | /// 51 | /// Indicates that marked method builds string by format pattern and (optional) arguments. 52 | /// Parameter, which contains format string, should be given in constructor. 53 | /// The format string should be in -like form 54 | /// 55 | [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 56 | internal sealed class StringFormatMethodAttribute : Attribute 57 | { 58 | private readonly string myFormatParameterName; 59 | 60 | /// 61 | /// Initializes new instance of StringFormatMethodAttribute 62 | /// 63 | /// Specifies which parameter of an annotated method should be treated as format-string 64 | internal StringFormatMethodAttribute(string formatParameterName) 65 | { 66 | myFormatParameterName = formatParameterName; 67 | } 68 | 69 | /// 70 | /// Gets format parameter name 71 | /// 72 | internal string FormatParameterName 73 | { 74 | get { return myFormatParameterName; } 75 | } 76 | } 77 | 78 | /// 79 | /// Indicates that the function argument should be string literal and match one of the parameters of the caller function. 80 | /// For example, has such parameter. 81 | /// 82 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] 83 | internal sealed class InvokerParameterNameAttribute : Attribute 84 | { 85 | } 86 | 87 | /// 88 | /// Indicates that the marked method is assertion method, i.e. it halts control flow if one of the conditions is satisfied. 89 | /// To set the condition, mark one of the parameters with attribute 90 | /// 91 | /// 92 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 93 | internal sealed class AssertionMethodAttribute : Attribute 94 | { 95 | } 96 | 97 | /// 98 | /// Indicates the condition parameter of the assertion method. 99 | /// The method itself should be marked by attribute. 100 | /// The mandatory argument of the attribute is the assertion type. 101 | /// 102 | /// 103 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] 104 | internal sealed class AssertionConditionAttribute : Attribute 105 | { 106 | private readonly AssertionConditionType myConditionType; 107 | 108 | /// 109 | /// Initializes new instance of AssertionConditionAttribute 110 | /// 111 | /// Specifies condition type 112 | internal AssertionConditionAttribute(AssertionConditionType conditionType) 113 | { 114 | myConditionType = conditionType; 115 | } 116 | 117 | /// 118 | /// Gets condition type 119 | /// 120 | internal AssertionConditionType ConditionType 121 | { 122 | get { return myConditionType; } 123 | } 124 | } 125 | 126 | /// 127 | /// Specifies assertion type. If the assertion method argument satisifes the condition, then the execution continues. 128 | /// Otherwise, execution is assumed to be halted 129 | /// 130 | internal enum AssertionConditionType 131 | { 132 | /// 133 | /// Indicates that the marked parameter should be evaluated to true 134 | /// 135 | IS_TRUE = 0, 136 | 137 | /// 138 | /// Indicates that the marked parameter should be evaluated to false 139 | /// 140 | IS_FALSE = 1, 141 | 142 | /// 143 | /// Indicates that the marked parameter should be evaluated to null value 144 | /// 145 | IS_NULL = 2, 146 | 147 | /// 148 | /// Indicates that the marked parameter should be evaluated to not null value 149 | /// 150 | IS_NOT_NULL = 3, 151 | } 152 | 153 | /// 154 | /// Indicates that the marked method unconditionally terminates control flow execution. 155 | /// For example, it could unconditionally throw exception 156 | /// 157 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 158 | internal sealed class TerminatesProgramAttribute : Attribute 159 | { 160 | } 161 | 162 | /// 163 | /// Indicates that the value of marked element could be null sometimes, so the check for null is necessary before its usage 164 | /// 165 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] 166 | internal sealed class CanBeNullAttribute : Attribute 167 | { 168 | } 169 | 170 | /// 171 | /// Indicates that the value of marked element could never be null 172 | /// 173 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] 174 | internal sealed class NotNullAttribute : Attribute 175 | { 176 | } 177 | 178 | /// 179 | /// Indicates that the value of marked type (or its derivatives) cannot be compared using '==' or '!=' operators. 180 | /// There is only exception to compare with null, it is permitted 181 | /// 182 | [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)] 183 | internal sealed class CannotApplyEqualityOperatorAttribute : Attribute 184 | { 185 | } 186 | 187 | /// 188 | /// When applied to target attribute, specifies a requirement for any type which is marked with 189 | /// target attribute to implement or inherit specific type or types 190 | /// 191 | /// 192 | /// 193 | /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement 194 | /// internal class ComponentAttribute : Attribute 195 | /// {} 196 | /// 197 | /// [Component] // ComponentAttribute requires implementing IComponent interface 198 | /// internal class MyComponent : IComponent 199 | /// {} 200 | /// 201 | /// 202 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] 203 | [BaseTypeRequired(typeof(Attribute))] 204 | internal sealed class BaseTypeRequiredAttribute : Attribute 205 | { 206 | private readonly Type[] myBaseTypes; 207 | 208 | /// 209 | /// Initializes new instance of BaseTypeRequiredAttribute 210 | /// 211 | /// Specifies which types are required 212 | internal BaseTypeRequiredAttribute(params Type[] baseTypes) 213 | { 214 | myBaseTypes = baseTypes; 215 | } 216 | 217 | /// 218 | /// Gets enumerations of specified base types 219 | /// 220 | internal IEnumerable BaseTypes 221 | { 222 | get { return myBaseTypes; } 223 | } 224 | } 225 | 226 | /// 227 | /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), 228 | /// so this symbol will not be marked as unused (as well as by other usage inspections) 229 | /// 230 | [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)] 231 | internal sealed class UsedImplicitlyAttribute : Attribute 232 | { 233 | [UsedImplicitly] 234 | internal UsedImplicitlyAttribute() 235 | : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) 236 | { 237 | } 238 | 239 | [UsedImplicitly] 240 | internal UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) 241 | { 242 | UseKindFlags = useKindFlags; 243 | TargetFlags = targetFlags; 244 | } 245 | 246 | [UsedImplicitly] 247 | internal UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) 248 | : this(useKindFlags, ImplicitUseTargetFlags.Default) 249 | { 250 | } 251 | 252 | [UsedImplicitly] 253 | internal UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) 254 | : this(ImplicitUseKindFlags.Default, targetFlags) 255 | { 256 | } 257 | 258 | [UsedImplicitly] 259 | internal ImplicitUseKindFlags UseKindFlags { get; private set; } 260 | 261 | /// 262 | /// Gets value indicating what is meant to be used 263 | /// 264 | [UsedImplicitly] 265 | internal ImplicitUseTargetFlags TargetFlags { get; private set; } 266 | } 267 | 268 | /// 269 | /// Should be used on attributes and causes ReSharper to not mark symbols marked with such attributes as unused (as well as by other usage inspections) 270 | /// 271 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 272 | internal sealed class MeansImplicitUseAttribute : Attribute 273 | { 274 | [UsedImplicitly] 275 | internal MeansImplicitUseAttribute() 276 | : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) 277 | { 278 | } 279 | 280 | [UsedImplicitly] 281 | internal MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) 282 | { 283 | UseKindFlags = useKindFlags; 284 | TargetFlags = targetFlags; 285 | } 286 | 287 | [UsedImplicitly] 288 | internal MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) 289 | : this(useKindFlags, ImplicitUseTargetFlags.Default) 290 | { 291 | } 292 | 293 | [UsedImplicitly] 294 | internal MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) 295 | : this(ImplicitUseKindFlags.Default, targetFlags) 296 | { 297 | } 298 | 299 | [UsedImplicitly] 300 | internal ImplicitUseKindFlags UseKindFlags { get; private set; } 301 | 302 | /// 303 | /// Gets value indicating what is meant to be used 304 | /// 305 | [UsedImplicitly] 306 | internal ImplicitUseTargetFlags TargetFlags { get; private set; } 307 | } 308 | 309 | [Flags] 310 | internal enum ImplicitUseKindFlags 311 | { 312 | Default = Access | Assign | Instantiated, 313 | 314 | /// 315 | /// Only entity marked with attribute considered used 316 | /// 317 | Access = 1, 318 | 319 | /// 320 | /// Indicates implicit assignment to a member 321 | /// 322 | Assign = 2, 323 | 324 | /// 325 | /// Indicates implicit instantiation of a type 326 | /// 327 | Instantiated = 4, 328 | } 329 | 330 | /// 331 | /// Specify what is considered used implicitly when marked with or 332 | /// 333 | [Flags] 334 | internal enum ImplicitUseTargetFlags 335 | { 336 | Default = Itself, 337 | 338 | Itself = 1, 339 | 340 | /// 341 | /// Members of entity marked with attribute are considered used 342 | /// 343 | Members = 2, 344 | 345 | /// 346 | /// Entity marked with attribute and all its members considered used 347 | /// 348 | WithMembers = Itself | Members 349 | } 350 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace PowerAssert 7 | { 8 | public static class Extensions 9 | { 10 | public static string CleanupName(this string name) 11 | { 12 | var tmp = name.CleanupUnderScores(); 13 | return tmp.CleanupCamelCasing(); 14 | } 15 | 16 | public static string CleanupUnderScores(this string name) 17 | { 18 | if (name.Contains('_')) 19 | return name.Replace('_', ' '); 20 | return name; 21 | } 22 | 23 | public static string CleanupCamelCasing(this string name) 24 | { 25 | return System.Text.RegularExpressions.Regex.Replace(name, 26 | "([A-Z])", 27 | " $1", 28 | System.Text.RegularExpressions.RegexOptions.Compiled 29 | ).Trim(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/ExpressionParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Reflection; 8 | using System.Runtime.CompilerServices; 9 | using PowerAssert.Infrastructure.Nodes; 10 | 11 | namespace PowerAssert.Infrastructure 12 | { 13 | internal class ExpressionParser 14 | { 15 | public static Node Parse(Expression e) 16 | { 17 | if (e.NodeType == ExpressionType.ArrayIndex) 18 | { 19 | return ArrayIndex((BinaryExpression)e); 20 | } 21 | if (e is BinaryExpression) 22 | { 23 | return Binary((BinaryExpression)e, Util.Operators[e.NodeType]); 24 | } 25 | if (e is MemberExpression) 26 | { 27 | return Member((MemberExpression)e); 28 | } 29 | if (e is ConstantExpression) 30 | { 31 | return Constant((ConstantExpression)e); 32 | } 33 | if (e is MethodCallExpression) 34 | { 35 | return MethodCall((MethodCallExpression)e); 36 | } 37 | if (e is ConditionalExpression) 38 | { 39 | return Conditional((ConditionalExpression)e); 40 | } 41 | if (e is NewArrayExpression) 42 | { 43 | return NewArray((NewArrayExpression)e); 44 | } 45 | if (e is UnaryExpression) 46 | { 47 | return Unary((UnaryExpression)e); 48 | } 49 | if (e.NodeType == ExpressionType.Lambda) 50 | { 51 | return Lambda(e); 52 | } 53 | if (e is TypeBinaryExpression) 54 | { 55 | return TypeBinary((TypeBinaryExpression)e); 56 | } 57 | throw new ArgumentOutOfRangeException("e", string.Format("Can't handle expression of class {0} and type {1}", e.GetType().Name, e.NodeType)); 58 | 59 | } 60 | 61 | static Node TypeBinary(TypeBinaryExpression e) 62 | { 63 | switch (e.NodeType) 64 | { 65 | case ExpressionType.TypeIs: 66 | return new BinaryNode() 67 | { 68 | Left = Parse(e.Expression), 69 | Operator = "is", 70 | Right = new ConstantNode() { Text = NameOfType(e.TypeOperand) }, 71 | Value = GetValue(e) 72 | }; 73 | default: 74 | throw new NotImplementedException(string.Format(CultureInfo.CurrentCulture, 75 | "Can't handle TypeBinaryExpression of type {0}", 76 | e.NodeType)); 77 | } 78 | } 79 | 80 | static Node Lambda(Expression e) 81 | { 82 | return new ConstantNode() { Text = e.ToString() }; 83 | } 84 | 85 | static Node Unary(UnaryExpression e) 86 | { 87 | switch (e.NodeType) 88 | { 89 | case ExpressionType.Convert: 90 | return new UnaryNode() { Prefix = "(" + NameOfType(e.Type) + ")(", Operand = Parse(e.Operand), Suffix = ")", PrefixValue = GetValue(e) }; 91 | case ExpressionType.Not: 92 | return new UnaryNode() { Prefix = "!", Operand = Parse(e.Operand), PrefixValue = GetValue(e) }; 93 | case ExpressionType.Negate: 94 | case ExpressionType.NegateChecked: 95 | return new UnaryNode() { Prefix = "-", Operand = Parse(e.Operand), PrefixValue = GetValue(e) }; 96 | 97 | 98 | } 99 | throw new ArgumentOutOfRangeException("e", string.Format("Can't handle UnaryExpression expression of class {0} and type {1}", e.GetType().Name, e.NodeType)); 100 | 101 | } 102 | 103 | static Node NewArray(NewArrayExpression e) 104 | { 105 | switch (e.NodeType) 106 | { 107 | case ExpressionType.NewArrayInit: 108 | Type t = e.Type.GetElementType(); 109 | return new NewArrayNode 110 | { 111 | Items = e.Expressions.Select(Parse).ToList(), 112 | Type = NameOfType(t) 113 | }; 114 | case ExpressionType.NewArrayBounds: 115 | //todo: 116 | default: 117 | throw new ArgumentOutOfRangeException(); 118 | } 119 | } 120 | 121 | private static readonly Dictionary Aliases = new Dictionary() 122 | { 123 | { typeof(byte), "byte" }, 124 | { typeof(sbyte), "sbyte" }, 125 | { typeof(short), "short" }, 126 | { typeof(ushort), "ushort" }, 127 | { typeof(int), "int" }, 128 | { typeof(uint), "uint" }, 129 | { typeof(long), "long" }, 130 | { typeof(ulong), "ulong" }, 131 | { typeof(float), "float" }, 132 | { typeof(double), "double" }, 133 | { typeof(decimal), "decimal" }, 134 | { typeof(object), "object" }, 135 | { typeof(string), "string" }, 136 | }; 137 | 138 | 139 | static string NameOfType(Type t) 140 | { 141 | return Aliases.ContainsKey(t) ? Aliases[t] : t.Name; 142 | } 143 | 144 | static Node ArrayIndex(BinaryExpression e) 145 | { 146 | return new ArrayIndexNode() { Array = Parse(e.Left), Index = Parse(e.Right), Value = GetValue(e) }; 147 | } 148 | 149 | static Node Conditional(ConditionalExpression e) 150 | { 151 | return new ConditionalNode 152 | { 153 | Condition = Parse(e.Test), 154 | FalseValue = Parse(e.IfFalse), 155 | TrueValue = Parse(e.IfTrue) 156 | }; 157 | } 158 | 159 | static Node MethodCall(MethodCallExpression e) 160 | { 161 | var parameters = e.Arguments.Select(Parse); 162 | if(e.Method.GetCustomAttributes(typeof(ExtensionAttribute), true).Any()) 163 | { 164 | return new MethodCallNode 165 | { 166 | Container = parameters.First(), 167 | MemberName = e.Method.Name, 168 | MemberValue = GetValue(e), 169 | Parameters = parameters.Skip(1).ToList(), 170 | }; 171 | } 172 | else 173 | { 174 | return new MethodCallNode 175 | { 176 | Container = e.Object == null ? new ConstantNode() { Text = e.Method.DeclaringType.Name } : Parse(e.Object), 177 | MemberName = e.Method.Name, 178 | MemberValue = GetValue(e), 179 | Parameters = parameters.ToList(), 180 | }; 181 | } 182 | 183 | } 184 | 185 | static Node Constant(ConstantExpression e) 186 | { 187 | string value = GetValue(e); 188 | 189 | return new ConstantNode 190 | { 191 | Text = value 192 | }; 193 | } 194 | 195 | static Node Member(MemberExpression e) 196 | { 197 | if (IsDisplayClass(e.Expression) || e.Expression == null) 198 | { 199 | return new ConstantNode 200 | { 201 | Value = GetValue(e), 202 | Text = e.Member.Name 203 | }; 204 | } 205 | return new MemberAccessNode 206 | { 207 | Container = Parse(e.Expression), 208 | MemberValue = GetValue(e), 209 | MemberName = e.Member.Name 210 | }; 211 | } 212 | 213 | 214 | static bool IsDisplayClass(Expression expression) 215 | { 216 | if (expression is ConstantExpression) 217 | { 218 | return expression.Type.Name.StartsWith("<"); 219 | } 220 | return false; 221 | } 222 | 223 | static Node Binary(BinaryExpression e, string text) 224 | { 225 | return new BinaryNode 226 | { 227 | Operator = text, 228 | Value = GetValue(e), 229 | Left = Parse(e.Left), 230 | Right = Parse(e.Right), 231 | }; 232 | } 233 | 234 | static string GetValue(Expression e) 235 | { 236 | object value; 237 | try 238 | { 239 | value = DynamicInvoke(e); 240 | } 241 | catch (TargetInvocationException exception) 242 | { 243 | return FormatTargetInvocationException(exception); 244 | } 245 | var s = FormatObject(value); 246 | return s + GetHints(e, value); 247 | } 248 | 249 | static string FormatTargetInvocationException(TargetInvocationException exception) 250 | { 251 | var i = exception.InnerException; 252 | return string.Format("{0}: {1}", i.GetType().Name, i.Message); 253 | } 254 | 255 | static string GetHints(Expression e, object value) 256 | { 257 | if (value is bool && !(bool)value && e is BinaryExpression && e.NodeType == ExpressionType.Equal) 258 | { 259 | var be = (BinaryExpression)e; 260 | object left; 261 | object right; 262 | try 263 | { 264 | left = DynamicInvoke(be.Left); 265 | right = DynamicInvoke(be.Right); 266 | } 267 | catch (TargetInvocationException exception) 268 | { 269 | return FormatTargetInvocationException(exception); 270 | } 271 | if (Object.Equals(left, right)) 272 | { 273 | return ", but would have been True with .Equals()"; 274 | } 275 | if (left is string && right is string) 276 | { 277 | if (((string)left).Equals((string)right, StringComparison.InvariantCultureIgnoreCase)) 278 | { 279 | return ", but would have been True if case insensitive"; 280 | } 281 | return ""; 282 | } 283 | if (left is IEnumerable && right is IEnumerable) 284 | { 285 | if (((IEnumerable)left).Cast().SequenceEqual(((IEnumerable)right).Cast())) 286 | { 287 | return ", but would have been True with .SequenceEqual()"; 288 | } 289 | } 290 | } 291 | return ""; 292 | } 293 | 294 | static object DynamicInvoke(Expression e) 295 | { 296 | return Expression.Lambda(e).Compile().DynamicInvoke(); 297 | } 298 | 299 | static string FormatObject(object value) 300 | { 301 | if (value == null) 302 | { 303 | return "null"; 304 | } 305 | if (value is string) 306 | { 307 | return "\"" + value + "\""; 308 | } 309 | if (value is char) 310 | { 311 | return "'" + value + "'"; 312 | } 313 | if (value is IEnumerable) 314 | { 315 | IEnumerable enumerable = (IEnumerable)value; 316 | var values = enumerable.Cast().Select(FormatObject); 317 | //in case the enumerable is really long, let's cut off the end arbitrarily? 318 | const int Limit = 100; 319 | values = values.Take(Limit); 320 | if(values.Count() == Limit) 321 | { 322 | values = values.Concat(new[] { "... (MORE THAN " + Limit + " ITEMS FOUND)" }); 323 | } 324 | return "{" + string.Join(", ", values.ToArray()) + "}"; 325 | } 326 | if (value is Exception) return value.GetType().Name; 327 | if (value.GetType().IsValueType) return value.ToString(); 328 | return value.GetType().Name; 329 | } 330 | } 331 | } 332 | 333 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/NodeFormatter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using PowerAssert.Infrastructure.Nodes; 6 | 7 | namespace PowerAssert.Infrastructure 8 | { 9 | internal class NodeFormatter 10 | { 11 | const char pipe = '|'; 12 | const char dot = '\''; 13 | internal static string SimpleFormat(Node constantNode) 14 | { 15 | var textLine = new StringBuilder(); 16 | var nodeInfos = new List(); 17 | 18 | GetSimpleFormatString(constantNode, nodeInfos, textLine); 19 | return textLine.ToString(); 20 | } 21 | internal static string[] Format(Node constantNode) 22 | { 23 | var textLine = new StringBuilder(); 24 | var nodeInfos = new List(); 25 | 26 | GetSimpleFormatString(constantNode, nodeInfos, textLine); 27 | 28 | var lines = new List(); 29 | 30 | var stalks = new List(); 31 | foreach (var info in nodeInfos.OrderBy(x => x.Location)) 32 | { 33 | var line = new StringBuilder(new string(' ', info.Location)); 34 | stalks.ForEach(x => line[x] = pipe); 35 | stalks.Add(info.Location); 36 | line.Append(info.Value); 37 | lines.Add(line); 38 | } 39 | 40 | if(nodeInfos.Any()) 41 | { 42 | for (int i = nodeInfos.Max(x=>x.Depth)-1; i >= 0 ; i--) 43 | { 44 | var line = new StringBuilder(new string(' ', nodeInfos.Max(x=>x.Location)+1)); 45 | nodeInfos.ForEach(x => line[x.Location] = x.Depth > i ? dot : pipe); 46 | lines.Add(line); 47 | } 48 | } 49 | 50 | lines.Add(textLine); 51 | 52 | return lines 53 | .AsEnumerable() 54 | .Reverse() 55 | .Select(x => x.ToString().TrimEnd()) 56 | .Where(x=>x.Length > 0) 57 | .ToArray(); 58 | } 59 | 60 | private static void GetSimpleFormatString(Node constantNode, List nodeInfos, StringBuilder textLine) 61 | { 62 | constantNode.Walk((text, value, depth) => 63 | { 64 | if (value != null) 65 | { 66 | nodeInfos.Add(new NodeInfo { Location = textLine.Length, Value = value, Depth=depth }); 67 | } 68 | textLine.Append(text); 69 | }, 0); 70 | } 71 | 72 | class NodeInfo 73 | { 74 | public int Location { get; set; } 75 | public string Value { get; set; } 76 | public int Depth { get; set; } 77 | } 78 | 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Nodes/ArrayIndexNode.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace PowerAssert.Infrastructure.Nodes 4 | { 5 | internal class ArrayIndexNode : Node 6 | { 7 | [NotNull] 8 | public Node Array { get; set; } 9 | 10 | [NotNull] 11 | public Node Index { get; set; } 12 | 13 | [NotNull] 14 | public string Value { get; set; } 15 | 16 | internal override void Walk(NodeWalker walker, int depth) 17 | { 18 | Array.Walk(walker, depth + 1); 19 | walker("[", Value, depth); 20 | Index.Walk(walker, depth + 1); 21 | walker("]"); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Nodes/BinaryNode.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace PowerAssert.Infrastructure.Nodes 4 | { 5 | internal class BinaryNode : Node 6 | { 7 | [NotNull] 8 | public Node Left { get; set; } 9 | 10 | [NotNull] 11 | public Node Right { get; set; } 12 | 13 | [NotNull] 14 | public string Operator { get; set; } 15 | 16 | [CanBeNull] 17 | public string Value { get; set; } 18 | 19 | internal override void Walk(NodeWalker walker, int depth) 20 | { 21 | Left.Walk(walker, depth+1); 22 | walker(" "); 23 | walker(Operator, Value, depth); 24 | walker(" "); 25 | Right.Walk(walker, depth + 1); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Nodes/ConditionalNode.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace PowerAssert.Infrastructure.Nodes 4 | { 5 | internal class ConditionalNode : Node 6 | { 7 | [NotNull] 8 | public Node Condition { get; set; } 9 | 10 | [NotNull] 11 | public Node TrueValue { get; set; } 12 | 13 | [NotNull] 14 | public Node FalseValue { get; set; } 15 | 16 | internal override void Walk(NodeWalker walker, int depth) 17 | { 18 | walker("("); 19 | Condition.Walk(walker, depth + 1); 20 | walker(" ? "); 21 | TrueValue.Walk(walker, depth + 1); 22 | walker(" : "); 23 | FalseValue.Walk(walker, depth + 1); 24 | walker(")"); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Nodes/ConstantNode.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace PowerAssert.Infrastructure.Nodes 4 | { 5 | internal class ConstantNode : Node 6 | { 7 | [NotNull] 8 | public string Text { get; set; } 9 | 10 | [CanBeNull] 11 | public string Value { get; set; } 12 | 13 | internal override void Walk(NodeWalker walker, int depth) 14 | { 15 | walker(Text.CleanupCamelCasing(), Value, depth); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Nodes/MemberAccessNode.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace PowerAssert.Infrastructure.Nodes 4 | { 5 | internal class MemberAccessNode : Node 6 | { 7 | [NotNull] 8 | public Node Container { get; set; } 9 | 10 | [NotNull] 11 | public string MemberName { get; set; } 12 | 13 | [NotNull] 14 | public string MemberValue { get; set; } 15 | 16 | internal override void Walk(NodeWalker walker, int depth) 17 | { 18 | Container.Walk(walker, depth + 1); 19 | walker(" "); 20 | walker(MemberName.CleanupName(), MemberValue, depth); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Nodes/MethodCallNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using JetBrains.Annotations; 4 | 5 | namespace PowerAssert.Infrastructure.Nodes 6 | { 7 | internal class MethodCallNode : MemberAccessNode 8 | { 9 | internal MethodCallNode() 10 | { 11 | Parameters = new List(); 12 | } 13 | 14 | [NotNull] 15 | public List Parameters { get; set; } 16 | 17 | internal override void Walk(NodeWalker walker, int depth) 18 | { 19 | base.Walk(walker, depth); 20 | walker("("); 21 | foreach (var parameter in Parameters.Take(1)) 22 | { 23 | parameter.Walk(walker, depth); 24 | } 25 | foreach (var parameter in Parameters.Skip(1)) 26 | { 27 | walker(", "); 28 | parameter.Walk(walker, depth); 29 | } 30 | walker(")"); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Nodes/NewArrayNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using JetBrains.Annotations; 4 | 5 | namespace PowerAssert.Infrastructure.Nodes 6 | { 7 | internal class NewArrayNode : Node 8 | { 9 | [NotNull] 10 | public List Items { get; set; } 11 | 12 | [NotNull] 13 | public string Type { get; set; } 14 | 15 | internal override void Walk(NodeWalker walker, int depth) 16 | { 17 | walker("new " + Type + "[]{"); 18 | foreach (var node in Items.Take(1)) 19 | { 20 | node.Walk(walker, depth); 21 | } 22 | foreach (var node in Items.Skip(1)) 23 | { 24 | walker(", "); 25 | node.Walk(walker, depth); 26 | } 27 | walker("}"); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Nodes/Node.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Linq; 4 | 5 | namespace PowerAssert.Infrastructure.Nodes 6 | { 7 | internal abstract class Node 8 | { 9 | internal abstract void Walk(NodeWalker walker, int depth); 10 | internal delegate void NodeWalker(string text, string value = null, int depth = 0); 11 | 12 | public override bool Equals(object obj) 13 | { 14 | if(obj.GetType() != GetType()) 15 | { 16 | return false; 17 | } 18 | 19 | var allPropertiesMatch = from info in GetType().GetProperties() 20 | let mine = info.GetValue(this, null) 21 | let theirs = info.GetValue(obj, null) 22 | select ObjectsOrEnumerablesEqual(mine, theirs); 23 | 24 | return allPropertiesMatch.All(b => b); 25 | } 26 | 27 | static bool ObjectsOrEnumerablesEqual(object mine, object theirs) 28 | { 29 | if(mine == theirs) 30 | { 31 | return true; 32 | } 33 | if(mine == null || theirs == null) 34 | { 35 | return false; 36 | } 37 | return mine is IEnumerable ? ((IEnumerable) mine).Cast().SequenceEqual(((IEnumerable) theirs).Cast()) : mine.Equals(theirs); 38 | } 39 | 40 | public override int GetHashCode() 41 | { 42 | var v = from info in GetType().GetProperties() 43 | let value = info.GetValue(this, null) 44 | select value == null ? 0 : value.GetHashCode(); 45 | 46 | return v.Aggregate((x, y) => x ^ y * 397); 47 | } 48 | 49 | public override string ToString() 50 | { 51 | var strings = NodeFormatter.Format(this); 52 | return string.Join(Environment.NewLine, strings); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Nodes/UnaryNode.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace PowerAssert.Infrastructure.Nodes 4 | { 5 | internal class UnaryNode : Node 6 | { 7 | [CanBeNull] 8 | public string Prefix { get; set; } 9 | 10 | [CanBeNull] 11 | public string Suffix { get; set; } 12 | 13 | [NotNull] 14 | public Node Operand { get; set; } 15 | 16 | [CanBeNull] 17 | public string PrefixValue { get; set; } 18 | 19 | [CanBeNull] 20 | public string SuffixValue { get; set; } 21 | 22 | internal override void Walk(NodeWalker walker, int depth) 23 | { 24 | if (!string.IsNullOrEmpty(Prefix)) 25 | { 26 | walker(Prefix, PrefixValue, depth + 1); 27 | } 28 | Operand.Walk(walker, depth); 29 | if (!string.IsNullOrEmpty(Suffix)) 30 | { 31 | walker(Suffix, SuffixValue, depth + 1); 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Util.Generated.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | using System.Collections.Generic; 3 | 4 | namespace PowerAssert.Infrastructure 5 | { 6 | internal class Util 7 | { 8 | internal static Dictionary NaturalOperators = new Dictionary 9 | { 10 | {ExpressionType.AndAlso, "and"}, 11 | {ExpressionType.OrElse, "or"}, 12 | {ExpressionType.Add, "added to"}, 13 | {ExpressionType.AddChecked, "added to"}, 14 | {ExpressionType.And, "binary anded with"}, 15 | {ExpressionType.Divide, "divided by"}, 16 | {ExpressionType.Equal, "must be equal to"}, 17 | {ExpressionType.ExclusiveOr, "exclusive or'ed with"}, 18 | {ExpressionType.GreaterThan, "must be greater than"}, 19 | {ExpressionType.GreaterThanOrEqual, "must be greater than or equal to"}, 20 | {ExpressionType.LeftShift, "left shift by"}, 21 | {ExpressionType.LessThan, "must be less than"}, 22 | {ExpressionType.LessThanOrEqual, "must be less than or equal to"}, 23 | {ExpressionType.Modulo, "modulo"}, 24 | {ExpressionType.Multiply, "multiplied by"}, 25 | {ExpressionType.MultiplyChecked, "multiplied by"}, 26 | {ExpressionType.NotEqual, "must not be equal to"}, 27 | {ExpressionType.Or, "binary or'ed with"}, 28 | {ExpressionType.RightShift, "right shift by"}, 29 | {ExpressionType.Subtract, "subtracted by"}, 30 | {ExpressionType.SubtractChecked, "subtracted by"}, 31 | }; 32 | internal static Dictionary Operators = new Dictionary 33 | { 34 | {ExpressionType.AndAlso, "&&"}, 35 | {ExpressionType.OrElse, "||"}, 36 | {ExpressionType.Add, "+"}, 37 | {ExpressionType.AddChecked, "+"}, 38 | {ExpressionType.And, "&"}, 39 | {ExpressionType.Divide, "/"}, 40 | {ExpressionType.Equal, "=="}, 41 | {ExpressionType.ExclusiveOr, "^"}, 42 | {ExpressionType.GreaterThan, ">"}, 43 | {ExpressionType.GreaterThanOrEqual, ">="}, 44 | {ExpressionType.LeftShift, "<<"}, 45 | {ExpressionType.LessThan, "<"}, 46 | {ExpressionType.LessThanOrEqual, "<="}, 47 | {ExpressionType.Modulo, "%"}, 48 | {ExpressionType.Multiply, "*"}, 49 | {ExpressionType.MultiplyChecked, "*"}, 50 | {ExpressionType.NotEqual, "!="}, 51 | {ExpressionType.Or, "|"}, 52 | {ExpressionType.RightShift, ">>"}, 53 | {ExpressionType.Subtract, "-"}, 54 | {ExpressionType.SubtractChecked, "-"}, 55 | }; 56 | } 57 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Infrastructure/Util.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ output extension=".Generated.cs" #> 3 | <#@ import namespace="System.Linq.Expressions" #> 4 | <#@ assembly name="System.Core" #> 5 | using System.Linq.Expressions; 6 | using System.Collections.Generic; 7 | 8 | namespace PowerAssert.Infrastructure 9 | { 10 | internal class Util 11 | { 12 | internal static Dictionary Operators = new Dictionary 13 | { 14 | {ExpressionType.AndAlso, "&&"}, 15 | {ExpressionType.OrElse, "||"}, 16 | <# 17 | foreach( var v in Enum.GetValues(typeof(ExpressionType))) 18 | { 19 | try 20 | { 21 | string s = Expression.MakeBinary((ExpressionType)v, Expression.Constant(0), Expression.Constant(0)).ToString().Trim('(', ')', '0', ' '); 22 | #> 23 | {ExpressionType.<#=v#>, "<#=s#>"}, 24 | <# 25 | } 26 | catch 27 | { 28 | 29 | } 30 | } 31 | #> 32 | }; 33 | } 34 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/PAssert.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using PowerAssert.Infrastructure; 4 | using PowerAssert.Infrastructure.Nodes; 5 | 6 | namespace PowerAssert 7 | { 8 | public static class PAssert 9 | { 10 | public static TException Throws(Action a) where TException : Exception 11 | { 12 | try 13 | { 14 | a(); 15 | } 16 | catch(TException exception) 17 | { 18 | return exception; 19 | } 20 | 21 | throw new Exception("An exception of type " + typeof(TException).Name + " was expected, but no exception occured"); 22 | } 23 | 24 | public static void IsTrue(Expression> expression) 25 | { 26 | Func func = expression.Compile(); 27 | if (!func()) 28 | { 29 | throw CreateException(expression, "Assertion failed"); 30 | } 31 | } 32 | 33 | public static string CreateSimpleFormatFor(Expression> expression) 34 | { 35 | Node constantNode = NaturalExpressionParser.Parse(expression.Body); 36 | return NodeFormatter.SimpleFormat(constantNode); 37 | } 38 | 39 | static Exception CreateException(Expression> expression, string message) 40 | { 41 | Node constantNode = NaturalExpressionParser.Parse(expression.Body); 42 | string[] lines = NodeFormatter.Format(constantNode); 43 | string nl = Environment.NewLine; 44 | return new Exception(message + ", expression was:" + nl + nl + String.Join(nl, lines)); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/PowerAssertForked.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9} 9 | Library 10 | Properties 11 | PowerAssert 12 | PowerAssert 13 | v3.5 14 | 512 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | release\lib\ 36 | TRACE 37 | true 38 | none 39 | AnyCPU 40 | bin\Release\PowerAssert.dll.CodeAnalysisLog.xml 41 | true 42 | GlobalSuppressions.cs 43 | prompt 44 | MinimumRecommendedRules.ruleset 45 | ;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 46 | false 47 | ;C:\Program Files\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 48 | false 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | True 71 | True 72 | Util.tt 73 | 74 | 75 | 76 | 77 | 78 | 79 | TextTemplatingFileGenerator 80 | Util.Generated.cs 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 96 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssert/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PowerAssert")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyProduct("PowerAssert")] 12 | [assembly: AssemblyCopyright("Copyright © Rob Fonseca-Ensor")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("38c2191d-b5ee-4d7c-b999-0002e0331c65")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.2.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | [assembly: InternalsVisibleTo("PowerAssertTests")] 37 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssertTests/EndToEndTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using NUnit.Framework; 7 | using PowerAssert; 8 | using PowerAssert.Infrastructure; 9 | using PowerAssert.Infrastructure.Nodes; 10 | 11 | namespace PowerAssertTests 12 | { 13 | /// 14 | /// Summary description for UnitTest1 15 | /// 16 | [TestFixture] 17 | public class EndToEndTest 18 | { 19 | 20 | 21 | [Test] 22 | public void PrintResults() 23 | { 24 | int x = 11; 25 | int y = 6; 26 | DateTime d = new DateTime(2010, 3, 1); 27 | Expression> expression = () => x + 5 == d.Month * y; 28 | Node constantNode = ExpressionParser.Parse(expression.Body); 29 | string[] strings = NodeFormatter.Format(constantNode); 30 | string s = string.Join(Environment.NewLine, strings); 31 | Console.Out.WriteLine(s); 32 | } 33 | 34 | [Test] 35 | [Ignore("This test will fail for demo purposes")] 36 | public void RunComplexExpression() 37 | { 38 | int x = 11; 39 | int y = 6; 40 | DateTime d = new DateTime(2010, 3, 1); 41 | PAssert.IsTrue(() => x + 5 == d.Month * y); 42 | } 43 | 44 | static int field = 11; 45 | [Test] 46 | [Ignore("This test will fail for demo purposes")] 47 | public void RunComplexExpressionWithStaticField() 48 | { 49 | int y = 6; 50 | DateTime d = new DateTime(2010, 3, 1); 51 | PAssert.IsTrue(() => field + 5 == d.Month * y); 52 | } 53 | 54 | [Test] 55 | [Ignore("This test will fail for demo purposes")] 56 | public void RunComplexExpression2() 57 | { 58 | string x = " lalalaa "; 59 | int i = 10; 60 | PAssert.IsTrue(() => x.Trim().Length == Math.Max(4, new int[] { 5, 4, i / 3, 2 }[0])); 61 | } 62 | 63 | [Test] 64 | [Ignore("This test will fail for demo purposes")] 65 | public void RunComplexExpression3() 66 | { 67 | List l = new List { 1, 2, 3 }; 68 | bool b = false; 69 | PAssert.IsTrue(() => l[2].ToString() == (b ? "three" : "four")); 70 | } 71 | 72 | [Test] 73 | [Ignore("This test will fail for demo purposes")] 74 | public void RunStringCompare() 75 | { 76 | string s = "hello, bobby"; 77 | Tuple t = new Tuple("hello, Bobby"); 78 | PAssert.IsTrue(() => s == t.Item1); 79 | } 80 | 81 | [Test] 82 | [Ignore("This test will fail for demo purposes")] 83 | public void RunRoundingEdgeCase() 84 | { 85 | double d = 3; 86 | int i = 2; 87 | 88 | 89 | PAssert.IsTrue(() => 4.5 == d + 3 / i); 90 | } 91 | 92 | [Test] 93 | [Ignore("This test will fail for demo purposes")] 94 | public void EqualsButNotOperatorEquals() 95 | { 96 | var t1 = new Tuple("foo"); 97 | var t2 = new Tuple("foo"); 98 | 99 | PAssert.IsTrue(() => t1 == t2); 100 | } 101 | 102 | [Test] 103 | [Ignore("This test will fail for demo purposes")] 104 | public void SequenceEqualButNotOperatorEquals() 105 | { 106 | object list = new List{1,2,3}; 107 | object array = new[] { 1, 2, 3 }; 108 | PAssert.IsTrue(() => list == array); 109 | } 110 | 111 | [Test] 112 | [Ignore("This test will fail for demo purposes")] 113 | public void PrintingLinqStatements() 114 | { 115 | var list = Enumerable.Range(0, 150); 116 | PAssert.IsTrue(() => list.Where(x=>x%2==0).Sum() == 0); 117 | } 118 | 119 | [Test] 120 | [Ignore("This test will fail for demo purposes")] 121 | public void PrintingLinqExpressionStatements() 122 | { 123 | var list = Enumerable.Range(0, 150); 124 | PAssert.IsTrue(() => (from l in list where l%2==0 select l).Sum() == 0); 125 | } 126 | 127 | [Test] 128 | [Ignore("This test will fail for demo purposes")] 129 | public void PrintingComplexLinqExpressionStatements() 130 | { 131 | var list = Enumerable.Range(0, 5); 132 | PAssert.IsTrue(() => (from x in list from y in list where x > y select x + "," + y).Count() == 0); 133 | } 134 | 135 | [Test] 136 | [Ignore("This test will fail for demo purposes")] 137 | public void PrintingEnumerablesWithNulls() 138 | { 139 | var list = new List{1,2,null,4,5}; 140 | PAssert.IsTrue(() => list.Sum() == null); 141 | } 142 | 143 | [Test] 144 | [Ignore("This test will fail for demo purposes")] 145 | public void PrintingUnaryNot() 146 | { 147 | var b = true; 148 | PAssert.IsTrue(() => !b); 149 | } 150 | 151 | [Test] 152 | [Ignore("This test will fail for demo purposes")] 153 | public void PrintingUnaryNegate() 154 | { 155 | var b = 5; 156 | PAssert.IsTrue(() => -b==0); 157 | } 158 | 159 | [Test] 160 | [Ignore("This test will fail for demo purposes")] 161 | public void PrintingIsTest() 162 | { 163 | var b = new object(); 164 | PAssert.IsTrue(() => b is string); 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssertTests/NodeFormatterTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using NUnit.Framework; 4 | using PowerAssert.Infrastructure; 5 | using PowerAssert.Infrastructure.Nodes; 6 | 7 | namespace PowerAssertTests 8 | { 9 | [TestFixture] 10 | public class NodeFormatterTest 11 | { 12 | [Test] 13 | public void FormatConstant() 14 | { 15 | string[] s = NodeFormatter.Format(new ConstantNode {Text = "5", Value = null}); 16 | AssertLines(new[] { "5" }, s); 17 | } 18 | 19 | [Test] 20 | public void FormatOperator() 21 | { 22 | string[] s = NodeFormatter.Format(new BinaryNode 23 | { 24 | Operator = "==", 25 | Value = "false", 26 | Left = new ConstantNode {Text = "5"}, 27 | Right = new ConstantNode {Text = "6"} 28 | }); 29 | 30 | string[] expected = { 31 | "5 == 6", 32 | " false" 33 | }; 34 | 35 | AssertLines(expected, s); 36 | } 37 | 38 | [Test] 39 | public void FormatTwoOperators() 40 | { 41 | string[] s = NodeFormatter.Format(new BinaryNode 42 | { 43 | Operator = "==", 44 | Value = "false", 45 | Left = new ConstantNode {Text = "31"}, 46 | Right = new BinaryNode 47 | { 48 | Operator = "*", 49 | Value = "30", 50 | Left = new ConstantNode { Text = "5" }, 51 | Right = new ConstantNode { Text = "6" } 52 | } 53 | }); 54 | 55 | string[] expected = { 56 | "31 == 5 * 6", 57 | " │ ∙", 58 | " │ 30", 59 | " false" 60 | }; 61 | 62 | AssertLines(expected, s); 63 | } 64 | 65 | static void AssertLines(string[] expected, string[] actual) 66 | { 67 | Assert.AreEqual(string.Join(Environment.NewLine, expected), string.Join(Environment.NewLine, actual)); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssertTests/ParserTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using NUnit.Framework; 6 | using PowerAssert.Infrastructure; 7 | using PowerAssert.Infrastructure.Nodes; 8 | 9 | namespace PowerAssertTests 10 | { 11 | [TestFixture] 12 | public class ParserTest 13 | { 14 | static int field = 5; 15 | 16 | [Test] 17 | public void ParsePrimitiveConstant() 18 | { 19 | Expression> f = () => 5; 20 | ConstantNode constantNode = ExpressionParser.Parse(f.Body) as ConstantNode; 21 | Assert.AreEqual("5", constantNode.Text); 22 | } 23 | 24 | [Test] 25 | public void ParsePrimitiveStaticField() 26 | { 27 | Expression> f = () => field; 28 | ConstantNode constantNode = ExpressionParser.Parse(f.Body) as ConstantNode; 29 | Assert.AreEqual("field", constantNode.Text); 30 | Assert.AreEqual("5", constantNode.Value); 31 | } 32 | 33 | [Test] 34 | public void ParseStringConstant() 35 | { 36 | Expression> f = () => "foo"; 37 | ConstantNode constantNode = ExpressionParser.Parse(f.Body) as ConstantNode; 38 | Assert.AreEqual("\"foo\"", constantNode.Text); 39 | } 40 | 41 | [Test] 42 | public void ParseMember() 43 | { 44 | int x = 5; 45 | Expression> f = () => x; 46 | Node constantNode = ExpressionParser.Parse(f.Body); 47 | Assert.AreEqual(new ConstantNode { Text = "x", Value = "5" }, constantNode); 48 | 49 | } 50 | 51 | [Test] 52 | public void ParseMemberAccess() 53 | { 54 | DateTime d = new DateTime(2010, 12, 25); 55 | Expression> f = () => d.Day; 56 | MemberAccessNode node = (MemberAccessNode)ExpressionParser.Parse(f.Body); 57 | 58 | MemberAccessNode expected = new MemberAccessNode 59 | { 60 | Container = new ConstantNode { Text = "d", Value = d.ToString() }, 61 | MemberName = "Day", 62 | MemberValue = "25" 63 | }; 64 | 65 | Assert.AreEqual(expected, node); 66 | } 67 | [Test] 68 | public void ParseMethodAccess() 69 | { 70 | string s = "hello"; 71 | Expression> f = () => s.Substring(1); 72 | var node = ExpressionParser.Parse(f.Body); 73 | 74 | var expected = new MethodCallNode 75 | { 76 | Container = new ConstantNode { Text = "s", Value = @"""hello""" }, 77 | MemberName = "Substring", 78 | MemberValue = @"""ello""", 79 | Parameters = new List() { new ConstantNode { Text = "1" } } 80 | 81 | }; 82 | 83 | Assert.AreEqual(expected, node); 84 | } 85 | 86 | [Test] 87 | public void ParseMethodWithException() 88 | { 89 | Expression> f = () => ThrowException(); 90 | var node = ExpressionParser.Parse(f.Body); 91 | 92 | var expected = new MethodCallNode 93 | { 94 | Container = new ConstantNode { Text = "PowerAssertTests.ParserTest"}, 95 | MemberName = "ThrowException", 96 | MemberValue = @"DivideByZeroException: Attempted to divide by zero.", 97 | 98 | }; 99 | 100 | Assert.AreEqual(expected, node); 101 | } 102 | 103 | int ThrowException() 104 | { 105 | var d = 0; 106 | return 1/d; 107 | } 108 | 109 | [Test] 110 | public void ParseConditional() 111 | { 112 | bool b = false; 113 | Expression> f = () => b ? 1 : 2; 114 | var node = ExpressionParser.Parse(f.Body); 115 | 116 | var expected = new ConditionalNode 117 | { 118 | Condition = new ConstantNode { Text = "b", Value = "False" }, 119 | TrueValue = new ConstantNode { Text = "1" }, 120 | FalseValue = new ConstantNode { Text = "2" }, 121 | }; 122 | 123 | Assert.AreEqual(expected, node); 124 | } 125 | 126 | [Test] 127 | public void ParseArrayCreateAndIndex() 128 | { 129 | Expression> f = () => new int[] { 1, 2, 3 }[1]; 130 | var node = ExpressionParser.Parse(f.Body); 131 | 132 | var expected = new ArrayIndexNode 133 | { 134 | Array = new NewArrayNode 135 | { 136 | Type = "int", 137 | Items = new List 138 | { 139 | new ConstantNode{Text= "1"}, 140 | new ConstantNode{Text= "2"}, 141 | new ConstantNode{Text= "3"}, 142 | } 143 | }, 144 | Index = new ConstantNode { Text = "1"}, 145 | Value = "2" 146 | }; 147 | 148 | Assert.AreEqual(expected, node); 149 | } 150 | 151 | [Test] 152 | public void ParseCast() 153 | { 154 | double x = 5.1; 155 | Expression> f = () => (int)x; 156 | var node = ExpressionParser.Parse(f.Body); 157 | 158 | var expected = new UnaryNode 159 | { 160 | Prefix = "(int)(", 161 | PrefixValue = "5", 162 | Operand = new ConstantNode(){Text = "x", Value = 5.1M.ToString()}, 163 | Suffix = ")" 164 | }; 165 | 166 | Assert.AreEqual(expected, node); 167 | } 168 | 169 | [Test] 170 | public void ParseIsOperator() 171 | { 172 | object x = "xValue"; 173 | Expression> f = () => x is string; 174 | 175 | var node = ExpressionParser.Parse(f.Body); 176 | var expected = new BinaryNode() 177 | { 178 | Left = new ConstantNode() {Text = "x", Value = "\"xValue\""}, 179 | Operator = "is", 180 | Right = new ConstantNode() { Text = "string" }, 181 | Value = "True" 182 | }; 183 | 184 | Assert.AreEqual(expected, node); 185 | } 186 | 187 | [Test] 188 | public void ParseUnaryNot() 189 | { 190 | var v = true; 191 | Expression> f = () => !v; 192 | var node = ExpressionParser.Parse(f.Body); 193 | 194 | var expected = new UnaryNode 195 | { 196 | Prefix = "!", 197 | PrefixValue = "False", 198 | Operand = new ConstantNode(){Text = "v", Value = "True"}, 199 | }; 200 | 201 | Assert.AreEqual(expected, node); 202 | } 203 | 204 | [Test] 205 | public void ParseUnaryNegate() 206 | { 207 | var v = 5; 208 | Expression> f = () => -v; 209 | var node = ExpressionParser.Parse(f.Body); 210 | 211 | var expected = new UnaryNode 212 | { 213 | Prefix = "-", 214 | PrefixValue = "-5", 215 | Operand = new ConstantNode(){Text = "v", Value = "5"}, 216 | }; 217 | 218 | Assert.AreEqual(expected, node); 219 | } 220 | 221 | [Test] 222 | public void ParseEnumerableWithNulls() 223 | { 224 | var v = new List{1,2,null,4}; 225 | Expression>> f = () => v; 226 | var node = ExpressionParser.Parse(f.Body); 227 | 228 | var expected = new ConstantNode() 229 | { 230 | Text = "v", 231 | Value = "{1, 2, null, 4}" 232 | 233 | }; 234 | 235 | Assert.AreEqual(expected, node); 236 | } 237 | 238 | [Test] 239 | public void ParseBinaryWithNullLeftHandSide() 240 | { 241 | string leftHandSide = null; 242 | Expression> f = () => leftHandSide == "foo"; 243 | var node = ExpressionParser.Parse(f.Body); 244 | var expected = new BinaryNode 245 | { 246 | Left = new ConstantNode { Text = "leftHandSide", Value = "null" }, 247 | Right = new ConstantNode { Text = "\"foo\"" }, 248 | Operator = "==", 249 | Value = "False" 250 | }; 251 | 252 | Assert.AreEqual(expected, node); 253 | } 254 | 255 | [Test] 256 | public void ParseBinaryWithNullRightHandSide() 257 | { 258 | string rightHandSide = null; 259 | Expression> f = () => "foo" == rightHandSide; 260 | var node = ExpressionParser.Parse(f.Body); 261 | var expected = new BinaryNode 262 | { 263 | Left = new ConstantNode { Text = "\"foo\"" }, 264 | Right = new ConstantNode { Text = "rightHandSide", Value = "null" }, 265 | Operator = "==", 266 | Value = "False" 267 | }; 268 | 269 | Assert.AreEqual(expected, node); 270 | } 271 | } 272 | } -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssertTests/PowerAssertTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 7 | 8 | 2.0 9 | {665FDD28-99EF-4038-9469-1B27F778BF1D} 10 | Library 11 | Properties 12 | PowerAssertTests 13 | PowerAssertTests 14 | v4.0 15 | 512 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\lib\nunit.framework.dll 37 | 38 | 39 | 40 | 3.5 41 | 42 | 43 | 44 | 45 | False 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9} 58 | PowerAssert 59 | 60 | 61 | 62 | 69 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssertTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PowerAssertTests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyProduct("PowerAssertTests")] 12 | [assembly: AssemblyCopyright("Copyright © Rob Fonseca-Ensor")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("b66d2326-b90c-4500-9aca-2158fde6e1e4")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | [assembly: AssemblyVersion("1.0.0.0")] 34 | [assembly: AssemblyFileVersion("1.0.0.0")] 35 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/PowerAssertTests/ThrowsTest.cs: -------------------------------------------------------------------------------- 1 | namespace PowerAssertTests 2 | { 3 | using System; 4 | using NUnit.Framework; 5 | using PowerAssert; 6 | 7 | [TestFixture] 8 | public class ThrowsTest 9 | { 10 | [Test] 11 | public void Should_fail_when_expression_does_not_throw_an_exception() 12 | { 13 | try 14 | { 15 | PAssert.Throws(() => MethodThatDoesNotThrowAnException()); 16 | } 17 | catch 18 | { 19 | return; 20 | } 21 | 22 | throw new Exception("Expected throws assertion to fail."); 23 | } 24 | 25 | [Test] 26 | public void Should_succeed_when_expression_does_throw_an_exception() 27 | { 28 | PAssert.Throws(() => MethodThatDoesThrow(new Exception())); 29 | } 30 | 31 | [Test] 32 | public void Should_return_the_thrown_exception() 33 | { 34 | var expectedException = new Exception(); 35 | 36 | var actualException = PAssert.Throws(() => MethodThatDoesThrow(expectedException)); 37 | 38 | Assert.That(actualException, Is.EqualTo(expectedException)); 39 | } 40 | 41 | [Test] 42 | public void Should_fail_if_thrown_exception_is_of_wrong_type() 43 | { 44 | try 45 | { 46 | PAssert.Throws(() => MethodThatDoesThrow(new NullReferenceException())); 47 | } 48 | catch 49 | { 50 | return; 51 | } 52 | 53 | throw new Exception("Expected throws assertion to fail."); 54 | } 55 | 56 | private static void MethodThatDoesNotThrowAnException() 57 | { 58 | //NOP 59 | } 60 | 61 | private static void MethodThatDoesThrow(Exception ex) 62 | { 63 | throw ex; 64 | } 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/powerassert/powerassert/lib/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregoryyoung/Simple.Testing/80e8cb06dc19d6d08c7ee9c48ba4a91c77d0c52a/lib/powerassert/powerassert/lib/nunit.framework.dll -------------------------------------------------------------------------------- /src/DocGeneratorExample/AccountSpecifications.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Simple.Testing.ClientFramework; 5 | 6 | namespace DocGeneratorExample 7 | { 8 | public class AccountSpecifications 9 | { 10 | public Specification when_constructing_an_account() 11 | { 12 | return new ConstructorSpecification() 13 | { 14 | When = () => new Account("Jane Smith", 17), 15 | Expect = 16 | { 17 | account => account.AccountHolderName == "Jane Smith", 18 | account => account.UniqueIdentifier == 17, 19 | account => account.CurrentBalance == new Money(0m), 20 | account => account.Transactions.Count() == 0 21 | } 22 | }; 23 | } 24 | 25 | public Specification when_depositing_to_a_new_account() 26 | { 27 | return new ActionSpecification() 28 | { 29 | Before = 30 | () => SystemTime.Set(new DateTime(2011, 1, 1)), 31 | On = () => new Account("Joe User", 14), 32 | When = account => account.Deposit(new Money(50)), 33 | Expect = 34 | { 35 | account => account.CurrentBalance == new Money(50), 36 | account => account.Transactions.Count() == 1, 37 | account => account.Transactions.First().Amount == new Money(50), 38 | account => account.Transactions.First().Type == TransactionType.Deposit, 39 | account => account.Transactions.First().Timestamp == new DateTime(2011, 1, 1), 40 | }, 41 | Finally = SystemTime.Clear 42 | }; 43 | } 44 | 45 | public Specification when_withdrawing_to_overdraw_an_account() 46 | { 47 | return new FailingSpecification() 48 | { 49 | On = () => new Account("Joe User", 14), 50 | When = 51 | account => account.Withdraw(new Money(50)), 52 | Expect = 53 | { 54 | exception => exception.Message == "The operation would overdraw the account" 55 | } 56 | }; 57 | } 58 | 59 | public Specification when_witdrawing_from_account_with_sufficient_funds() 60 | { 61 | return new ActionSpecification 62 | { 63 | Before = () => SystemTime.Set(new DateTime(2011, 1, 1)), 64 | On = () => new Account("Joe User", 14, new Money(100)), 65 | When = account => account.Withdraw(new Money(50)), 66 | Expect = 67 | { 68 | account => account.CurrentBalance == new Money(50), 69 | account => account.Transactions.Count() == 1, 70 | account => account.Transactions.First().Amount == new Money(-5), 71 | account => account.Transactions.First().Type == TransactionType.Deposit, 72 | }, 73 | Finally = SystemTime.Clear 74 | }; 75 | } 76 | } 77 | 78 | class Account 79 | { 80 | public string AccountHolderName { get; private set; } 81 | public int UniqueIdentifier { get; private set; } 82 | public Money CurrentBalance { get { return _balance; } } 83 | private Money _balance = 0.Dollars(); 84 | 85 | private List _transactions = new List(); 86 | public IEnumerable Transactions { get { return _transactions; } } 87 | 88 | public Account(string accountHolder, int uniqueIdentifier) : this(accountHolder, uniqueIdentifier, new Money(0)) 89 | { 90 | } 91 | 92 | public Account(string accountHolder, int uniqueIdentifier, Money startingBalance) 93 | { 94 | AccountHolderName = accountHolder; 95 | UniqueIdentifier = uniqueIdentifier; 96 | _balance = startingBalance; 97 | } 98 | 99 | public override string ToString() 100 | { 101 | var ret = String.Format("Account: {0} owned by {1} with a balance {2}\n", UniqueIdentifier, AccountHolderName, 102 | CurrentBalance); 103 | if (_transactions.Count == 0) return ret + "\tWith no previous transactions."; 104 | ret = _transactions.Aggregate(ret, (current, t) => current + ("\t" + t.ToString() + "\n")); 105 | return ret; 106 | } 107 | 108 | public void Deposit(Money amount) 109 | { 110 | _balance += amount; 111 | _transactions.Add(new Transaction(amount, TransactionType.Deposit)); 112 | } 113 | 114 | public void Withdraw(Money amount) 115 | { 116 | if(_balance - amount < new Money(0)) 117 | { 118 | throw new CannotOverdrawAccountException("The operation would overdraw the account"); 119 | } 120 | _balance -= amount; 121 | _transactions.Add(new Transaction(new Money(0) - amount, TransactionType.Deposit)); 122 | } 123 | } 124 | 125 | internal class CannotOverdrawAccountException : Exception 126 | { 127 | public CannotOverdrawAccountException(string message) : base(message) 128 | { 129 | 130 | } 131 | } 132 | 133 | internal class Transaction 134 | { 135 | public Money Amount { get; private set; } 136 | public TransactionType Type { get; private set; } 137 | public DateTime Timestamp { get; private set; } 138 | public Transaction(Money amount, TransactionType type) 139 | { 140 | Amount = amount; 141 | Type = type; 142 | Timestamp = SystemTime.GetTime(); 143 | } 144 | 145 | public override string ToString() 146 | { 147 | return Type + " for " + Amount + " at " + Timestamp; 148 | } 149 | } 150 | 151 | internal static class SystemTime 152 | { 153 | private static DateTime setTime = DateTime.MinValue; 154 | 155 | public static void Clear() 156 | { 157 | setTime = DateTime.MinValue; 158 | } 159 | 160 | public static void Set(DateTime toSet) 161 | { 162 | setTime = toSet; 163 | } 164 | public static DateTime GetTime() 165 | { 166 | if (setTime == DateTime.MinValue) return DateTime.Now; 167 | return setTime; 168 | } 169 | } 170 | 171 | struct Money 172 | { 173 | private decimal _amount; 174 | public decimal Amount 175 | { 176 | get { return _amount; } 177 | set { _amount = value; } 178 | } 179 | 180 | public Money(decimal amount) 181 | { 182 | _amount = amount; 183 | } 184 | 185 | public override string ToString() 186 | { 187 | return "$" + Amount; 188 | } 189 | 190 | public override bool Equals(object obj) 191 | { 192 | if (obj == null || GetType() != obj.GetType()) 193 | { 194 | return false; 195 | } 196 | return Amount.Equals(((Money) obj).Amount); 197 | } 198 | 199 | public static bool operator ==(Money c1, Money c2) 200 | { 201 | return c1._amount == c2.Amount; 202 | } 203 | 204 | public static bool operator !=(Money c1, Money c2) 205 | { 206 | return !(c1 == c2); 207 | } 208 | 209 | public static Money operator +(Money c1, Money c2) 210 | { 211 | return new Money(c1._amount + c2._amount); 212 | } 213 | 214 | public static bool operator <(Money c1, Money c2) 215 | { 216 | return c1._amount < c2._amount; 217 | } 218 | 219 | public static bool operator >(Money c1, Money c2) 220 | { 221 | return c1._amount > c2._amount; 222 | } 223 | 224 | public static Money operator -(Money c1, Money c2) 225 | { 226 | return new Money(c1._amount - c2._amount); 227 | } 228 | public override int GetHashCode() 229 | { 230 | return Amount.GetHashCode(); 231 | } 232 | } 233 | 234 | static class Extensions 235 | { 236 | public static Money Dollars(this decimal amount) 237 | { 238 | return new Money(amount); 239 | } 240 | 241 | public static Money Dollars(this int amount) 242 | { 243 | return new Money(amount); 244 | } 245 | } 246 | 247 | enum TransactionType 248 | { 249 | Withdrawl, 250 | Deposit 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /src/DocGeneratorExample/DocGeneratorExample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {60800BA0-9F82-4CE4-A283-5BC27CC7DE04} 9 | Exe 10 | Properties 11 | DocGeneratorExample 12 | DocGeneratorExample 13 | v3.5 14 | 15 | 16 | 512 17 | 18 | 19 | x86 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | 28 | 29 | x86 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {AFE5EA9F-2829-4D63-9850-34803552C793} 54 | Simple.Testing.ClientFramework 55 | 56 | 57 | {A245A823-1DA4-4086-A265-158DC379B446} 58 | Simple.Testing.Example 59 | 60 | 61 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9} 62 | Simple.Testing.Framework 63 | 64 | 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /src/DocGeneratorExample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Simple.Testing.Framework; 3 | 4 | namespace DocGeneratorExample 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | SimpleRunner.RunAllInAssembly(typeof(Program).Assembly).ForEach(PrintSpec); 11 | } 12 | 13 | private static void PrintSpec(RunResult result) 14 | { 15 | var passed = result.Passed ? "Passed" : "Failed"; 16 | Console.WriteLine(result.Name.Replace('_', ' ') + " - " +passed); 17 | var on = result.GetOnResult(); 18 | if(on != null) 19 | { 20 | Console.WriteLine(); 21 | Console.WriteLine("On:"); 22 | Console.WriteLine(on.ToString()); 23 | Console.WriteLine(); 24 | } 25 | if (result.Result != null) 26 | { 27 | Console.WriteLine(); 28 | Console.WriteLine("Results with:"); 29 | if(result.Result is Exception) 30 | Console.WriteLine(result.Result.GetType() + "\n" + ((Exception) result.Result).Message ); 31 | else 32 | Console.WriteLine(result.Result.ToString()); 33 | Console.WriteLine(); 34 | } 35 | 36 | Console.WriteLine("Expectations:"); 37 | foreach(var expecation in result.Expectations) 38 | { 39 | if(expecation.Passed) 40 | Console.WriteLine("\t" + expecation.Text + " " + (expecation.Passed ? "Passed" : "Failed")); 41 | else 42 | Console.WriteLine(expecation.Exception.Message); 43 | } 44 | if(result.Thrown != null) 45 | { 46 | Console.WriteLine("Specification failed: " + result.Message); 47 | Console.WriteLine(); 48 | Console.WriteLine(result.Thrown); 49 | } 50 | Console.WriteLine(new string('-', 80)); 51 | Console.WriteLine(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/DocGeneratorExample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DocGeneratorExample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DocGeneratorExample")] 13 | [assembly: AssemblyCopyright("Copyright © 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e6e39eee-1bf9-4e6d-b7bf-a380f7606f45")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/DocGeneratorExample/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Simple.Testing.CientFramework/Simple.Testing.ClientFramework.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {AFE5EA9F-2829-4D63-9850-34803552C793} 9 | Library 10 | Properties 11 | Simple.Testing.ClientFramework 12 | Simple.Testing.ClientFramework 13 | v3.5 14 | 512 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 55 | -------------------------------------------------------------------------------- /src/Simple.Testing.CientFramework/SpecificationTemplates.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace Simple.Testing.ClientFramework 6 | { 7 | public delegate void WhenAction(T item); 8 | public delegate bool Expectation(T obj); 9 | 10 | public interface TypedSpecification : Specification 11 | { 12 | Action GetBefore(); 13 | Delegate GetOn(); 14 | Delegate GetWhen(); 15 | IEnumerable>> GetAssertions(); 16 | Action GetFinally(); 17 | } 18 | 19 | public interface Specification 20 | { 21 | string GetName(); 22 | } 23 | 24 | public class TransformedSpecification : TypedSpecification 25 | { 26 | public Action Before; 27 | public Func On; 28 | public Func When; 29 | public Func AndTransformedBy; 30 | public List>> Expect = new List>>(); 31 | public Action Finally; 32 | public string Name; 33 | 34 | public Action GetBefore() { return Before; } 35 | public Delegate GetOn() { return On; } 36 | public Delegate GetWhen() { return When; } 37 | public IEnumerable>> GetAssertions() { return Expect; } 38 | public Action GetFinally() { return Finally; } 39 | public string GetName() { return Name; } 40 | } 41 | 42 | public class QuerySpecification : TypedSpecification 43 | { 44 | public Action Before; 45 | public Func On; 46 | public Func When; 47 | public List>> Expect = new List>>(); 48 | public Action Finally; 49 | public string Name; 50 | 51 | public Action GetBefore() { return Before; } 52 | public Delegate GetOn() { return On; } 53 | public Delegate GetWhen() { return When; } 54 | public IEnumerable>> GetAssertions() { return Expect; } 55 | public Action GetFinally() { return Finally; } 56 | public string GetName() { return Name; } 57 | } 58 | 59 | public class ConstructorSpecification : TypedSpecification 60 | { 61 | public Action Before; 62 | public Func When; 63 | public List>> Expect = new List>>(); 64 | public Action Finally; 65 | public string Name; 66 | 67 | public Action GetBefore() { return Before; } 68 | public Delegate GetOn() {return (Action) (() => {});} 69 | public Delegate GetWhen() { return When; } 70 | public IEnumerable>> GetAssertions() { return Expect; } 71 | public Action GetFinally() { return Finally; } 72 | public string GetName() { return Name; } 73 | } 74 | 75 | public class ActionSpecification : TypedSpecification 76 | { 77 | public Action Before; 78 | public Func On; 79 | public Action When; 80 | public List>> Expect = new List>>(); 81 | public Action Finally; 82 | public string Name; 83 | 84 | public Action GetBefore() { return Before; } 85 | public Delegate GetOn() { return On; } 86 | public Delegate GetWhen() { return When; } 87 | public IEnumerable>> GetAssertions() { return Expect; } 88 | public Action GetFinally() { return Finally; } 89 | public string GetName() { return Name; } 90 | } 91 | 92 | public class FailingSpecification : TypedSpecification where TException : Exception 93 | { 94 | public Action Before; 95 | public Func On; 96 | public WhenAction When; 97 | public List>> Expect = new List>>(); 98 | public Action Finally; 99 | public string Name; 100 | 101 | public Action GetBefore() { return Before; } 102 | public Delegate GetOn() { return On; } 103 | public Delegate GetWhen() 104 | { 105 | return (Func) (x => 106 | { 107 | try 108 | { 109 | When(x); 110 | } 111 | catch (TException ex) 112 | { 113 | return ex; 114 | 115 | } 116 | catch(Exception ex) 117 | { 118 | throw ex; 119 | } 120 | throw new ExpectedExceptionDidNotOccurException(null); 121 | }); 122 | } 123 | 124 | 125 | public IEnumerable>> GetAssertions() { return Expect; } 126 | public Action GetFinally() { return Finally; } 127 | public string GetName() { return Name; } 128 | } 129 | 130 | public class ExpectedExceptionDidNotOccurException : Exception 131 | { 132 | public ExpectedExceptionDidNotOccurException(Exception innerException) : base((innerException == null) ? "Expected Exception did not occur " : "Caught " + innerException.GetType() + " instead", innerException) {} 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/Simple.Testing.ClientFramework/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Simple.Testing.ClientFramework")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Simple.Testing.ClientFramework")] 13 | [assembly: AssemblyCopyright("Copyright © 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("2e2a7059-f794-4e7c-8845-5f94f1af2c51")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/Simple.Testing.ClientFramework/Simple.Testing.ClientFramework.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {AFE5EA9F-2829-4D63-9850-34803552C793} 9 | Library 10 | Properties 11 | Simple.Testing.ClientFramework 12 | Simple.Testing.ClientFramework 13 | v3.5 14 | 512 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 55 | -------------------------------------------------------------------------------- /src/Simple.Testing.ClientFramework/SpecificationTemplates.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace Simple.Testing.ClientFramework 6 | { 7 | public delegate void WhenAction(T item); 8 | public delegate bool Expectation(T obj); 9 | 10 | public interface TypedSpecification : Specification 11 | { 12 | Action GetBefore(); 13 | Delegate GetOn(); 14 | Delegate GetWhen(); 15 | IEnumerable>> GetAssertions(); 16 | Action GetFinally(); 17 | } 18 | 19 | public interface Specification 20 | { 21 | string GetName(); 22 | } 23 | 24 | public class TransformedSpecification : TypedSpecification 25 | { 26 | public Action Before; 27 | public Func On; 28 | public Func When; 29 | public Func AndTransformedBy; 30 | public List>> Expect = new List>>(); 31 | public Action Finally; 32 | public string Name; 33 | 34 | public Action GetBefore() { return Before; } 35 | public Delegate GetOn() { return On; } 36 | public Delegate GetWhen() { return new Func(given => AndTransformedBy(When(given))); } 37 | public IEnumerable>> GetAssertions() { return Expect; } 38 | public Action GetFinally() { return Finally; } 39 | public string GetName() { return Name; } 40 | } 41 | 42 | public class QuerySpecification : TypedSpecification 43 | { 44 | public Action Before; 45 | public Func On; 46 | public Func When; 47 | public List>> Expect = new List>>(); 48 | public Action Finally; 49 | public string Name; 50 | 51 | public Action GetBefore() { return Before; } 52 | public Delegate GetOn() { return On; } 53 | public Delegate GetWhen() { return When; } 54 | public IEnumerable>> GetAssertions() { return Expect; } 55 | public Action GetFinally() { return Finally; } 56 | public string GetName() { return Name; } 57 | } 58 | 59 | public class ConstructorSpecification : TypedSpecification 60 | { 61 | public Action Before; 62 | public Func When; 63 | public List>> Expect = new List>>(); 64 | public Action Finally; 65 | public string Name; 66 | 67 | public Action GetBefore() { return Before; } 68 | public Delegate GetOn() {return (Action) (() => {});} 69 | public Delegate GetWhen() { return When; } 70 | public IEnumerable>> GetAssertions() { return Expect; } 71 | public Action GetFinally() { return Finally; } 72 | public string GetName() { return Name; } 73 | } 74 | 75 | public class ActionSpecification : TypedSpecification 76 | { 77 | public Action Before; 78 | public Func On; 79 | public Action When; 80 | public List>> Expect = new List>>(); 81 | public Action Finally; 82 | public string Name; 83 | 84 | public Action GetBefore() { return Before; } 85 | public Delegate GetOn() { return On; } 86 | public Delegate GetWhen() { return When; } 87 | public IEnumerable>> GetAssertions() { return Expect; } 88 | public Action GetFinally() { return Finally; } 89 | public string GetName() { return Name; } 90 | } 91 | 92 | public class FailingSpecification : TypedSpecification where TException : Exception 93 | { 94 | public Action Before; 95 | public Func On; 96 | public WhenAction When; 97 | public List>> Expect = new List>>(); 98 | public Action Finally; 99 | public string Name; 100 | 101 | public Action GetBefore() { return Before; } 102 | public Delegate GetOn() { return On; } 103 | public Delegate GetWhen() 104 | { 105 | return (Func) (x => 106 | { 107 | try 108 | { 109 | When(x); 110 | } 111 | catch (TException ex) 112 | { 113 | return ex; 114 | } 115 | catch(Exception ex) 116 | { 117 | throw ex; 118 | } 119 | 120 | throw new ExpectedExceptionDidNotOccurException(null); 121 | }); 122 | } 123 | 124 | 125 | public IEnumerable>> GetAssertions() { return Expect; } 126 | public Action GetFinally() { return Finally; } 127 | public string GetName() { return Name; } 128 | } 129 | 130 | public class ExpectedExceptionDidNotOccurException : Exception 131 | { 132 | public ExpectedExceptionDidNotOccurException(Exception innerException) : base((innerException == null) ? "Expected Exception did not occur " : "Caught " + innerException.GetType() + " instead", innerException) {} 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/Simple.Testing.Example/DataDrivenSpecification.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Simple.Testing.ClientFramework; 4 | 5 | namespace Simple.Testing.Example 6 | { 7 | /* 8 | * This sample shows the building of a data driven specification. This is the simplest 9 | * version of a generator. Basically the runner will call anything that returns an IEnumerable. 10 | * You can customize how the specifications are returned. In this case multiple specifications are 11 | * generated, based on the data involved. In this case, four specifications are returned. 12 | * 13 | * With a little bit of work this could also be made much more generic (eg to support all data driven specs) 14 | */ 15 | public class DataDrivenSpecifications 16 | { 17 | public IEnumerable when_adding_numbers() 18 | { 19 | return AddingTestData().Select(x => 20 | (Specification) new QuerySpecification 21 | { 22 | Name = "when adding numbers '" + x.Name + "'", 23 | On = () => new Calculator(), 24 | When = calc => calc.Add(x.OperandOne, x.OperantTwo), 25 | Expect = 26 | { 27 | result => result == x.ExpectedResult 28 | }, 29 | }); 30 | } 31 | 32 | public IEnumerable AddingTestData() 33 | { 34 | yield return new AddArgs { OperandOne = 1, OperantTwo = 1, ExpectedResult = 2 }; 35 | yield return new AddArgs { OperandOne = -1, OperantTwo = 1, ExpectedResult = 0 }; 36 | yield return new AddArgs { OperandOne = 50, OperantTwo = -55, ExpectedResult = -5 }; 37 | yield return new AddArgs { OperandOne = 0, OperantTwo = 0, ExpectedResult = 0 }; 38 | } 39 | } 40 | 41 | public class Calculator 42 | { 43 | public int Add(int x, int y) 44 | { 45 | return x + y; 46 | } 47 | } 48 | 49 | public class AddArgs 50 | { 51 | public string Name 52 | { 53 | get { return OperandOne + "+" + OperantTwo + "=" + ExpectedResult; } 54 | } 55 | public int OperandOne; 56 | public int OperantTwo; 57 | public int ExpectedResult; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Simple.Testing.Example/FailingSpecification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Simple.Testing.ClientFramework; 3 | 4 | namespace Simple.Testing.Example 5 | { 6 | /* 7 | * Sometimes the point of a specification is to show that a given scenario fails. 8 | * 9 | * A failing specification is similar to a SUT specification. It will return the SUT 10 | * from its On() method. The SUT will then be passed to the when() method where some 11 | * action will happen. It is expected that this action will throw an exception. 12 | * 13 | * The exception is then passed to the expectations. 14 | * 15 | * note: if you are doing more complex operations other templates can be used with 16 | * the TestContext pattern. 17 | */ 18 | public class FailingSpecification 19 | { 20 | public Specification it_will_fail() 21 | { 22 | return new FailingSpecification < FailingExample, SomethingFailedException > 23 | { 24 | On = () => new FailingExample(), 25 | When = (obj) => obj.CauseFailure(), 26 | Expect = 27 | { 28 | exception => exception.Message == "Something failed!", 29 | exception => exception.ErrorCode == 17 30 | } 31 | }; 32 | } 33 | } 34 | 35 | public class FailingExample 36 | { 37 | public void CauseFailure() 38 | { 39 | throw new SomethingFailedException("Something failed!", 17); 40 | } 41 | } 42 | 43 | public class SomethingFailedException : Exception 44 | { 45 | public readonly int ErrorCode; 46 | public SomethingFailedException(string msg, int errorCode) : base(msg) 47 | { 48 | ErrorCode = errorCode; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Simple.Testing.Example/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Simple.Testing.Example")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Simple.Testing.Example")] 13 | [assembly: AssemblyCopyright("Copyright © 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("07353174-43bd-401d-8b21-5d860c0b79d3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/Simple.Testing.Example/QuerySpecification.cs: -------------------------------------------------------------------------------- 1 | using Simple.Testing.ClientFramework; 2 | 3 | namespace Simple.Testing.Example 4 | { 5 | /* 6 | * A query specification is intended to be used on a method with a return value. The 7 | * general idea is that the On() will build the SUT. The when() will call the method 8 | * returning the methods return value. The expectations are then on the returned value. 9 | * 10 | * You may wonder how you can assert on the sut after the call. You can't using this 11 | * template. This is by design, see CQS by Bertrand Meyer, you should not mutate state 12 | * of the object when querying. If you want to break this rule use a more open template 13 | * and specialize it. 14 | */ 15 | public class QuerySepcification 16 | { 17 | public Specification it_returns_something_interesting() 18 | { 19 | return new QuerySpecification 20 | { 21 | On = () => new QueryExample(), 22 | When = obj => obj.GetProduct(14), 23 | Expect = 24 | { 25 | product => product.Id == 14, 26 | product => product.Code == "TEST", 27 | product => product.Description == "test description" 28 | }, 29 | }; 30 | } 31 | } 32 | 33 | public class QueryExample 34 | { 35 | public Product GetProduct(int id) 36 | { 37 | return new Product(id, "TEST", "test description"); 38 | } 39 | } 40 | 41 | public class Product 42 | { 43 | public readonly int Id; 44 | public readonly string Code; 45 | public readonly string Description; 46 | 47 | public Product(int id, string code, string description) 48 | { 49 | Id = id; 50 | Description = description; 51 | Code = code; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Simple.Testing.Example/Simple.Testing.Example.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {A245A823-1DA4-4086-A265-158DC379B446} 9 | Library 10 | Properties 11 | Simple.Testing.Example 12 | Simple.Testing.Example 13 | v3.5 14 | 512 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {AFE5EA9F-2829-4D63-9850-34803552C793} 53 | Simple.Testing.ClientFramework 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /src/Simple.Testing.Example/SutSpecification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Simple.Testing.ClientFramework; 3 | 4 | namespace Simple.Testing.Example 5 | { 6 | /* 7 | * In an action specification the SUT is returned from the On(). The SUT is then given 8 | * as a parameter to the When and the Expects. It is expected that the when() will 9 | * issue some behavior that mutates the SUT which is then sent to the expectations. 10 | */ 11 | public class ActionSpecifications 12 | { 13 | public Specification when_withdrawing_money_from_empty_account() 14 | { 15 | return new ActionSpecification 16 | { 17 | On = () => new Depositor(13), 18 | When = depositor => depositor.Withdraw(50.00m), 19 | Expect = 20 | { 21 | depositor => depositor.Balance > 0.01m, 22 | depositor => depositor.AccountIsOpen, 23 | depositor => depositor.Balance > .50m 24 | }, 25 | }; 26 | } 27 | 28 | private static decimal GetOverallCount() 29 | { 30 | return 12; 31 | } 32 | } 33 | 34 | 35 | public class Depositor 36 | { 37 | private readonly int _depositorId; 38 | public readonly decimal Balance = 50.00m; 39 | public readonly bool AccountIsOpen = true; 40 | public void Withdraw(decimal amount) 41 | { 42 | } 43 | public Depositor(int depositorId) 44 | { 45 | _depositorId = depositorId; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework.Tests/MightyMooseIgnoreAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Simple.Testing.Framework.Tests 4 | { 5 | public class MightyMooseIgnoreAttribute : Attribute {} 6 | } -------------------------------------------------------------------------------- /src/Simple.Testing.Framework.Tests/NamedMethodGeneratorTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using Simple.Testing.ClientFramework; 6 | 7 | namespace Simple.Testing.Framework.Tests 8 | { 9 | public class NamedMethodGeneratorTests 10 | { 11 | public Specification when_finding_a_method_on_normal_class() 12 | { 13 | return new QuerySpecification>() 14 | { 15 | On = () => new NamedMethodsGenerator(Assembly.GetExecutingAssembly(), 16 | "Simple.Testing.Framework.Tests.NamedGeneratorTestsData.A_Test"), 17 | When = runner => runner.GetSpecifications(), 18 | Expect = 19 | { 20 | result => result.Count() == 1, 21 | result => result.First().FoundOn.Name == "A_Test", 22 | result => result.First().IsRunnable, 23 | result => result.First().Exception == null, 24 | result => 25 | result.First().Specification.GetType() == typeof (PassingSpecification), 26 | } 27 | }; 28 | } 29 | 30 | public Specification when_finding_a_method_on_nested_class() 31 | { 32 | return new QuerySpecification>() 33 | { 34 | On = 35 | () => 36 | new NamedMethodsGenerator(Assembly.GetExecutingAssembly(), 37 | "Simple.Testing.Framework.Tests.NamedGeneratorTestsData+Nested.A_Test"), 38 | When = runner => runner.GetSpecifications(), 39 | Expect = 40 | { 41 | result => result.Count() == 1, 42 | result => result.First().FoundOn.Name == "A_Test", 43 | result => result.First().IsRunnable, 44 | result => result.First().Exception == null, 45 | result => result.First().Specification.GetType() == typeof (PassingSpecification), 46 | } 47 | }; 48 | } 49 | 50 | public Specification when_finding_a_non_existant_method() 51 | { 52 | return new FailingSpecification() 53 | { 54 | On = () =>new NamedMethodsGenerator(Assembly.GetExecutingAssembly(), 55 | "SomdasdaethingWrong.Testing.Framework.Tests.NamedGeneratorTestsData+Nested.A_Test"), 56 | When = runner => runner.GetSpecifications().ToList(), 57 | Expect = 58 | { 59 | exception => exception.ParamName == "method" 60 | } 61 | }; 62 | } 63 | } 64 | 65 | public class NamedGeneratorTestsData 66 | { 67 | public class Nested 68 | { 69 | public Specification A_Test() 70 | { 71 | return new PassingSpecification(); 72 | } 73 | } 74 | public Specification A_Test() 75 | { 76 | return new PassingSpecification(); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework.Tests/PartialApplicationVisitorSpecifications.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using Simple.Testing.ClientFramework; 4 | 5 | namespace Simple.Testing.Framework.Tests 6 | { 7 | public class PartialApplicationVisitorSpecifications 8 | { 9 | public Specification can_exchange_parameters_for_values() 10 | { 11 | return new QuerySpecification>> 12 | { 13 | On = () => null, 14 | When = q => PartialApplicationVisitor.Apply(x => 44 == x + 1, 43), 15 | Expect = 16 | { 17 | result => result.Compile().Invoke() 18 | } 19 | }; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/Simple.Testing.Framework.Tests/PassingSpecification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using Simple.Testing.ClientFramework; 5 | 6 | namespace Simple.Testing.Framework.Tests 7 | { 8 | public class PassingSpecification : TypedSpecification 9 | { 10 | public string GetName() 11 | { 12 | return ""; 13 | } 14 | 15 | public Action GetBefore() 16 | { 17 | return Noop; 18 | } 19 | 20 | private void Noop() 21 | { 22 | 23 | } 24 | 25 | public Delegate GetOn() 26 | { 27 | return new Action(Noop); 28 | } 29 | 30 | public Delegate GetWhen() 31 | { 32 | return new Action(Noop); 33 | } 34 | 35 | public IEnumerable>> GetAssertions() 36 | { 37 | return new List>>(); 38 | } 39 | 40 | public Action GetFinally() 41 | { 42 | return Noop; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/Simple.Testing.Framework.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Simple.Testing.Framework.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Simple.Testing.Framework.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a775fe41-f0d9-491f-8d8e-702a6637ccf3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework.Tests/Simple.Testing.Framework.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {25DA7F29-6653-40AA-BB99-35D4BDB840B0} 9 | Library 10 | Properties 11 | Simple.Testing.Framework.Tests 12 | Simple.Testing.Framework.Tests 13 | v3.5 14 | 512 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {AFE5EA9F-2829-4D63-9850-34803552C793} 54 | Simple.Testing.ClientFramework 55 | 56 | 57 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9} 58 | Simple.Testing.Framework 59 | 60 | 61 | 62 | 69 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework.Tests/SpecificationRunnerSpecifications.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Simple.Testing.ClientFramework; 3 | 4 | namespace Simple.Testing.Framework.Tests 5 | { 6 | public class SpecificationRunnerSpecifications 7 | { 8 | public Specification when_running_specification_with_exception_in_before() 9 | { 10 | return new QuerySpecification() 11 | { 12 | On = () => new SpecificationRunner(), 13 | When = runner => runner.RunSpecifciation(new TestSpecs().SpecWithExceptionInBefore().AsRunnable()), 14 | Expect = 15 | { 16 | result => result.Passed == false, 17 | result => result.Thrown is ArgumentException, 18 | result => result.Thrown.Message == "test", 19 | result => result.Message == "Before Failed", 20 | result => result.Expectations.Count == 0 21 | } 22 | }; 23 | } 24 | 25 | //TODO FIX ME 26 | //public Specification when_running_specification_with_exception_in_on = new QuerySpecification() 27 | //{ 28 | // On = () => new SpecificationRunner(), 29 | // When = runner => runner.RunSpecifciation(TestSpecs.SpecWithExceptionInOn.AsRunnable()), 30 | // Expect = 31 | // { 32 | // result => result.Passed == false, 33 | // result => result.Thrown is ArgumentException, 34 | // result => result.Thrown.Message == "test2", 35 | // result => result.Message == "On Failed", 36 | // result => result.Expectations.Count == 0 37 | // } 38 | //}; 39 | 40 | public Specification when_running_specification_with_no_when() 41 | { 42 | return new QuerySpecification() 43 | { 44 | On = () => new SpecificationRunner(), 45 | When = runner => runner.RunSpecifciation(new TestSpecs().SpecWithNoWhen().AsRunnable()), 46 | Expect = 47 | { 48 | result => result.Passed == false, 49 | result => result.Thrown == null, 50 | result => result.Message == "No when on specification", 51 | result => result.Expectations.Count == 0 52 | } 53 | }; 54 | } 55 | 56 | public Specification when_running_specification_with_exception_in_when() 57 | { 58 | return new QuerySpecification() 59 | { 60 | On = () => new SpecificationRunner(), 61 | When = runner => runner.RunSpecifciation(new TestSpecs().SpecWithExceptionInWhen().AsRunnable()), 62 | Expect = 63 | { 64 | result => result.Passed == false, 65 | result => result.Thrown is ArgumentException, 66 | result => result.Message == "When Failed", 67 | result => result.Expectations.Count == 0 68 | } 69 | }; 70 | } 71 | 72 | public Specification when_running_specification_with_exception_in_finally() 73 | { 74 | return new QuerySpecification() 75 | { 76 | On = () => new SpecificationRunner(), 77 | When = runner => runner.RunSpecifciation(new TestSpecs().SpecWithExceptionInFinally().AsRunnable()), 78 | Expect = 79 | { 80 | result => result.Passed == false, 81 | result => result.Thrown is ArgumentException, 82 | result => result.Message == "Finally failed", 83 | result => result.Expectations.Count == 1 84 | } 85 | }; 86 | } 87 | 88 | 89 | public Specification when_running_specification_with_exception_in_expectation() 90 | { 91 | return new QuerySpecification() 92 | { 93 | On = () => new SpecificationRunner(), 94 | When = 95 | runner => runner.RunSpecifciation(new TestSpecs().SpecWithExceptionInExpectation().AsRunnable()), 96 | Expect = 97 | { 98 | result => !result.Passed, 99 | result => result.Thrown == null, 100 | result => result.Message == null, 101 | result => result.Expectations.Count == 1, 102 | result => result.Expectations[0].Passed == false, 103 | result => result.Expectations[0].Exception is ArgumentException, 104 | result => result.Expectations[0].Exception.Message == "methodthatthrows" 105 | } 106 | }; 107 | } 108 | 109 | public Specification when_running_passing_specification_with_single_expectation() 110 | { 111 | return new QuerySpecification() 112 | { 113 | On = () => new SpecificationRunner(), 114 | When = 115 | runner => 116 | runner.RunSpecifciation(new TestSpecs().SpecWithSinglePassingExpectation().AsRunnable()), 117 | Expect = 118 | { 119 | result => result.Passed, 120 | result => result.Thrown == null, 121 | result => result.Message == null, 122 | result => result.Expectations.Count == 1, 123 | result => result.Expectations[0].Passed, 124 | result => result.Expectations[0].Exception == null, 125 | } 126 | }; 127 | } 128 | } 129 | 130 | public class TestSpecs 131 | { 132 | public ActionSpecification SpecWithExceptionInBefore() 133 | { 134 | return new ActionSpecification 135 | { 136 | Before = () => { throw new ArgumentException("test"); }, 137 | Expect = {x => x.Equals(3)} 138 | }; 139 | } 140 | 141 | //TODO FIX ME 142 | //public static TypedSpecification SpecWithExceptionInOn = new ActionSpecification 143 | //{ 144 | // On = () => { throw new ArgumentException("test2"); }, 145 | // When = data => data++, 146 | // Expect = {x => x.Equals(3)} 147 | //}; 148 | 149 | public TypedSpecification SpecWithNoWhen() 150 | { 151 | return new ActionSpecification 152 | { 153 | On = () => 3, 154 | Expect = {x => x.Equals(3)} 155 | }; 156 | } 157 | 158 | public TypedSpecification SpecWithExceptionInWhen() 159 | { 160 | return new ActionSpecification 161 | { 162 | On = () => 3, 163 | When = data => { throw new ArgumentException("test3"); }, 164 | Expect = {x => x.Equals(3)} 165 | }; 166 | } 167 | 168 | public TypedSpecification SpecWithExceptionInFinally() 169 | { 170 | return new ActionSpecification 171 | { 172 | On = () => 3, 173 | When = data => data++, 174 | Expect = {x => x.Equals(3)}, 175 | Finally = () => { throw new ArgumentException("test4"); } 176 | }; 177 | } 178 | 179 | public TypedSpecification SpecWithExceptionInExpectation() 180 | { 181 | return new ActionSpecification 182 | { 183 | On = () => 3, 184 | When = data => data++, 185 | Expect = {x => MethodThatThrows(x)} 186 | }; 187 | } 188 | 189 | public TypedSpecification SpecWithSinglePassingExpectation() 190 | { 191 | return new ActionSpecification 192 | { 193 | On = () => 3, 194 | When = data => data++, 195 | Expect = {x => x == x} 196 | }; 197 | } 198 | 199 | private static bool MethodThatThrows(object o) 200 | { 201 | throw new ArgumentException("methodthatthrows"); 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/ISpecificationGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Simple.Testing.Framework 4 | { 5 | public interface ISpecificationGenerator 6 | { 7 | IEnumerable GetSpecifications(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/NamedMethodsGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using Simple.Testing.ClientFramework; 6 | 7 | namespace Simple.Testing.Framework 8 | { 9 | public class NamedMethodsGenerator : ISpecificationGenerator 10 | { 11 | private readonly Assembly _assembly; 12 | private readonly List _methods = new List(); 13 | 14 | public NamedMethodsGenerator(Assembly assembly, string method) 15 | { 16 | _assembly = assembly; 17 | _methods.Add(method); 18 | } 19 | 20 | public NamedMethodsGenerator(Assembly assembly, IEnumerable methods) 21 | { 22 | _assembly = assembly; 23 | _methods.AddRange(methods); 24 | } 25 | 26 | public IEnumerable GetSpecifications() 27 | { 28 | foreach(var method in _methods) 29 | { 30 | var typename = GetTypeName(method); 31 | var methodname = GetMethodName(method); 32 | var type = _assembly.GetType(typename); 33 | if(type == null) throw new ArgumentException("Type not found", "method"); 34 | var allMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); 35 | var methodinfos = allMethods.Where(x => x.Name == methodname); 36 | foreach(var info in methodinfos) 37 | { 38 | SpecificationToRun toRun = null; 39 | if (typeof(Specification).IsAssignableFrom(info.ReturnType)) 40 | { 41 | try 42 | { 43 | var result = info.CallMethod(); 44 | if (result != null) toRun = new SpecificationToRun((Specification) result, info); 45 | } 46 | catch(Exception ex) 47 | { 48 | toRun = new SpecificationToRun(null, "Exception when creating specification", ex, info); 49 | } 50 | yield return toRun; 51 | } 52 | if (typeof(IEnumerable).IsAssignableFrom(info.ReturnType)) 53 | { 54 | var specsToRun = new List(); 55 | var specs = new List(); 56 | IEnumerable obj; 57 | bool error = false; 58 | try 59 | { 60 | obj = (IEnumerable) info.CallMethod(); 61 | specs = obj.ToList(); 62 | } 63 | catch(Exception ex) 64 | { 65 | specsToRun.Add(new SpecificationToRun(null, "Exception occured creating specification", ex, info)); 66 | error = true; 67 | } 68 | if(!error) 69 | { 70 | foreach (var item in specs) 71 | yield return new SpecificationToRun(item, info); 72 | } 73 | } 74 | } 75 | } 76 | } 77 | 78 | private string GetMethodName(string method) 79 | { 80 | var lastdot = method.LastIndexOf("."); 81 | if (lastdot == -1) return null; 82 | return method.Substring(lastdot + 1, method.Length - lastdot - 1); 83 | } 84 | 85 | private string GetTypeName(string method) 86 | { 87 | var lastdot = method.LastIndexOf("."); 88 | if (lastdot == -1) return null; 89 | return method.Substring(0, lastdot); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/OnTypeGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Simple.Testing.Framework 6 | { 7 | public class OnTypeGenerator : ISpecificationGenerator 8 | { 9 | private readonly List _types = new List(); 10 | 11 | public OnTypeGenerator(Type type) 12 | { 13 | _types.Add(type); 14 | } 15 | 16 | public OnTypeGenerator(IEnumerable types) 17 | { 18 | _types.AddRange(types); 19 | } 20 | 21 | public OnTypeGenerator(params Type[] types) : this((IEnumerable) types) 22 | { 23 | } 24 | 25 | public IEnumerable GetSpecifications() 26 | { 27 | return _types.SelectMany(TypeReader.GetSpecificationsIn); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Simple.Testing.Framework")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Simple.Testing.Framework")] 13 | [assembly: AssemblyCopyright("Copyright © 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("941a2e74-fa13-48b5-831e-c99461f8be4f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/RootGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Reflection; 4 | 5 | namespace Simple.Testing.Framework 6 | { 7 | public class RootGenerator : ISpecificationGenerator 8 | { 9 | private readonly Assembly _assembly; 10 | 11 | public RootGenerator(Assembly assembly) 12 | { 13 | _assembly = assembly; 14 | } 15 | 16 | public IEnumerable GetSpecifications() 17 | { 18 | return _assembly.GetTypes().SelectMany(TypeReader.GetSpecificationsIn); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/RunResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using System.Reflection; 5 | 6 | namespace Simple.Testing.Framework 7 | { 8 | public class RunResult 9 | { 10 | public bool Passed; 11 | public string Message; 12 | public Exception Thrown; 13 | public string SpecificationName; 14 | public List Expectations = new List(); 15 | public MemberInfo FoundOnMemberInfo; 16 | public Delegate On; 17 | public object Result; 18 | 19 | public object GetOnResult() 20 | { 21 | return On.DynamicInvoke(); 22 | } 23 | 24 | public string Name 25 | { 26 | get { return SpecificationName ?? FoundOnMemberInfo.Name; } 27 | } 28 | 29 | internal void MarkFailure(string message, Exception thrown) 30 | { 31 | Thrown = thrown; 32 | Message = message; 33 | Passed = false; 34 | } 35 | } 36 | 37 | 38 | public class ExpectationResult 39 | { 40 | public bool Passed; 41 | public string Text; 42 | public Exception Exception; 43 | public Expression OriginalExpression; 44 | } 45 | } -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/Simple.Testing.Framework.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {A6E67E2A-2A26-4016-BE26-D6F3141729D9} 9 | Library 10 | Properties 11 | Simple.Testing.Framework 12 | Simple.Testing.Framework 13 | v3.5 14 | 512 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | {7E9D2DB4-78FE-41BD-9566-15F68D42E4D9} 60 | PowerAssertForked 61 | 62 | 63 | {AFE5EA9F-2829-4D63-9850-34803552C793} 64 | Simple.Testing.ClientFramework 65 | 66 | 67 | 68 | 75 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/SimpleRunner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace Simple.Testing.Framework 7 | { 8 | public static class SimpleRunner 9 | { 10 | public static IEnumerable RunByName(Assembly assembly, string methodName) 11 | { 12 | return RunFromGenerator(new NamedMethodsGenerator(assembly, new[] {methodName})); 13 | } 14 | public static IEnumerable RunByName(Assembly assembly, IEnumerable methodNames) 15 | { 16 | return RunFromGenerator(new NamedMethodsGenerator(assembly, methodNames)); 17 | } 18 | public static IEnumerable RunAllInType(Assembly assembly, string typeName) 19 | { 20 | return RunAllInType(assembly.GetType(typeName)); 21 | } 22 | 23 | public static IEnumerable RunAllInType(Type t) 24 | { 25 | return RunFromGenerator(new OnTypeGenerator(t)); 26 | } 27 | 28 | public static IEnumerable RunAllInType() 29 | { 30 | return RunAllInType(typeof (T)); 31 | } 32 | 33 | public static IEnumerable RunAllInAssembly(string assemblyName) 34 | { 35 | var assembly = Assembly.LoadFrom(assemblyName); 36 | return RunAllInAssembly(assembly); 37 | } 38 | 39 | public static IEnumerable RunAllInAssembly(Assembly assembly) 40 | { 41 | return RunFromGenerator(new RootGenerator(assembly)); 42 | } 43 | 44 | public static IEnumerable RunFromGenerator(ISpecificationGenerator generator) 45 | { 46 | var runner = new SpecificationRunner(); 47 | return generator.GetSpecifications().Select(runner.RunSpecifciation); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/SpecificationRunner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using PowerAssert; 5 | using Simple.Testing.ClientFramework; 6 | 7 | namespace Simple.Testing.Framework 8 | { 9 | public class SpecificationRunner 10 | { 11 | public RunResult RunSpecifciation(SpecificationToRun spec) 12 | { 13 | if (!spec.IsRunnable) 14 | { 15 | return new RunResult 16 | { 17 | FoundOnMemberInfo = spec.FoundOn, 18 | Message = spec.Reason, 19 | Thrown = spec.Exception, 20 | Passed = false 21 | }; 22 | } 23 | var method = typeof(SpecificationRunner).GetMethod("Run", BindingFlags.NonPublic | BindingFlags.Instance); 24 | var tomake = spec.Specification.GetType().GetInterfaces().Single(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(TypedSpecification<>)); 25 | var generic = method.MakeGenericMethod(tomake.GetGenericArguments()[0]); 26 | var result = (RunResult) generic.Invoke(this, new object[] {spec.Specification, spec.FoundOn}); 27 | result.FoundOnMemberInfo = spec.FoundOn; 28 | return result; 29 | } 30 | 31 | private RunResult Run(TypedSpecification spec, MemberInfo foundon) 32 | { 33 | var result = new RunResult { SpecificationName = spec.GetName()}; 34 | RunResult runResult; 35 | object sut; 36 | object whenResult; 37 | Delegate when; 38 | 39 | if (RunSetup(spec, result, out runResult, out sut, out whenResult, out when)) return runResult; 40 | var fromWhen = when.Method.ReturnType == typeof(void) ? sut : whenResult; 41 | bool allOkForAssertions = true; 42 | bool allOkForTeardowns = true; 43 | //OK THIS IS A HACK! ITS HERE FOR PROFILING SUPPORT (I NEED TO BE ABLE TO GET THE METHOD OF THE ORIGINAL METHOD OF SPEC) 44 | var hack = foundon as MethodInfo; 45 | if (hack != null) 46 | { 47 | hack.CallMethod(); 48 | } 49 | //YOU CANNOT PUT A METHOD CALL BETWEEN LAST AND THIS ONE!!!! 50 | allOkForAssertions = RunAssertions(spec, result, fromWhen); 51 | allOkForTeardowns = RunTeardowns(spec, result); 52 | result.Passed = allOkForAssertions && allOkForTeardowns; 53 | return result; 54 | } 55 | 56 | private static bool RunTeardowns(TypedSpecification spec, RunResult result) 57 | { 58 | bool allOk = true; 59 | try 60 | { 61 | var Finally = spec.GetFinally(); 62 | Finally.InvokeIfNotNull(); 63 | } 64 | catch (Exception ex) 65 | { 66 | allOk = false; 67 | result.Message = "Finally failed"; 68 | result.Thrown = ex.InnerException; 69 | } 70 | return allOk; 71 | } 72 | 73 | private static bool RunAssertions(TypedSpecification spec, RunResult result, object fromWhen) 74 | { 75 | bool allOk = true; 76 | foreach (var exp in spec.GetAssertions()) 77 | { 78 | var partiallyApplied = PartialApplicationVisitor.Apply(exp, fromWhen); 79 | try 80 | { 81 | PAssert.IsTrue(partiallyApplied); 82 | result.Expectations.Add(new ExpectationResult 83 | { 84 | Passed = true, 85 | Text = PAssert.CreateSimpleFormatFor(partiallyApplied), 86 | OriginalExpression = exp 87 | }); 88 | } 89 | catch (Exception ex) 90 | { 91 | allOk = false; 92 | result.Expectations.Add(new ExpectationResult 93 | { 94 | Passed = false, 95 | Text = PAssert.CreateSimpleFormatFor(partiallyApplied), 96 | OriginalExpression = exp, 97 | Exception = ex 98 | }); 99 | } 100 | } 101 | return allOk; 102 | } 103 | 104 | private static bool RunSetup(TypedSpecification spec, RunResult result, out RunResult runResult, out object sut, 105 | out object whenResult, out Delegate when) 106 | { 107 | when = null; 108 | sut = null; 109 | whenResult = null; 110 | runResult = null; 111 | try 112 | { 113 | var before = spec.GetBefore(); 114 | before.InvokeIfNotNull(); 115 | } 116 | catch (Exception ex) 117 | { 118 | result.MarkFailure("Before Failed", ex.InnerException); 119 | { 120 | runResult = result; 121 | 122 | return true; 123 | } 124 | } 125 | sut = null; 126 | try 127 | { 128 | var given = spec.GetOn(); 129 | sut = given.DynamicInvoke(); 130 | result.On = given; 131 | } 132 | catch (Exception ex) 133 | { 134 | result.MarkFailure("On Failed", ex.InnerException); 135 | } 136 | whenResult = null; 137 | try 138 | { 139 | when = spec.GetWhen(); 140 | if (when == null) 141 | { 142 | runResult = new RunResult 143 | {SpecificationName = spec.GetName(), Passed = false, Message = "No when on specification"}; 144 | return true; 145 | } 146 | if (when.Method.GetParameters().Length == 1) 147 | whenResult = when.DynamicInvoke(new[] {sut}); 148 | else 149 | whenResult = when.DynamicInvoke(); 150 | if (when.Method.ReturnType != typeof (void)) 151 | result.Result = whenResult; 152 | else 153 | result.Result = sut; 154 | } 155 | catch (Exception ex) 156 | { 157 | result.MarkFailure("When Failed", ex.InnerException); 158 | { 159 | runResult = result; 160 | return true; 161 | } 162 | } 163 | return false; 164 | } 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/SpecificationToRun.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using Simple.Testing.ClientFramework; 4 | 5 | namespace Simple.Testing.Framework 6 | { 7 | public class SpecificationToRun 8 | { 9 | public readonly Specification Specification; 10 | public readonly MemberInfo FoundOn; 11 | public readonly bool IsRunnable; 12 | public readonly string Reason; 13 | public readonly Exception Exception; 14 | 15 | public SpecificationToRun(Specification specification, MemberInfo foundOn) 16 | { 17 | IsRunnable = true; 18 | Reason = ""; 19 | Exception = null; 20 | Specification = specification; 21 | FoundOn = foundOn; 22 | } 23 | 24 | public SpecificationToRun(Specification specification, string reason, Exception exception, MemberInfo foundOn) 25 | { 26 | FoundOn = foundOn; 27 | Specification = specification; 28 | Exception = exception; 29 | Reason = reason; 30 | IsRunnable = false; 31 | } 32 | 33 | public SpecificationToRun() {} 34 | } 35 | } -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/TypeReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using Simple.Testing.ClientFramework; 6 | 7 | namespace Simple.Testing.Framework 8 | { 9 | public static class TypeReader 10 | { 11 | public static IEnumerable GetSpecificationsIn(Type t) 12 | { 13 | foreach (var methodSpec in AllMethodSpecifications(t)) yield return methodSpec; 14 | foreach (var fieldSpec in AllFieldSpecifications(t)) yield return fieldSpec; 15 | } 16 | 17 | private static IEnumerable AllMethodSpecifications(Type t) 18 | { 19 | foreach (var s in t.GetMethods(BindingFlags.Public | BindingFlags.Instance)) 20 | { 21 | SpecificationToRun toRun = null; 22 | if (typeof(Specification).IsAssignableFrom(s.ReturnType)) 23 | { 24 | try 25 | { 26 | var result = s.CallMethod(); 27 | 28 | if (result != null) toRun = new SpecificationToRun((Specification)result, s); 29 | } 30 | catch (Exception ex) 31 | { 32 | toRun = new SpecificationToRun(null, "Exception when creating specification", ex, s); 33 | } 34 | yield return toRun; 35 | } 36 | if (typeof(IEnumerable).IsAssignableFrom(s.ReturnType)) 37 | { 38 | var specsToRun = new List(); 39 | var specs = new List(); 40 | IEnumerable obj; 41 | bool error = false; 42 | try 43 | { 44 | obj = (IEnumerable)s.CallMethod(); 45 | specs = obj.ToList(); 46 | } 47 | catch (Exception ex) 48 | { 49 | specsToRun.Add(new SpecificationToRun(null, "Exception occured creating specification", ex, s)); 50 | error = true; 51 | } 52 | if (!error) 53 | { 54 | foreach (var item in specs) 55 | yield return new SpecificationToRun(item, s); 56 | } 57 | } 58 | } 59 | } 60 | 61 | private static IEnumerable AllFieldSpecifications(Type t) 62 | { 63 | foreach (var m in t.GetFields(BindingFlags.Public | BindingFlags.Instance)) 64 | { 65 | if (typeof(Specification).IsAssignableFrom(m.FieldType)) 66 | { 67 | var spec = (Specification) m.GetValue(Activator.CreateInstance(t)); 68 | if(spec != null) 69 | yield return new SpecificationToRun(spec, m); 70 | } 71 | if (typeof(IEnumerable).IsAssignableFrom(m.FieldType)) 72 | { 73 | var obj = (IEnumerable)m.GetValue(Activator.CreateInstance(t)); 74 | if (obj != null) 75 | { 76 | foreach (var item in obj) 77 | yield return new SpecificationToRun(item, m); 78 | } 79 | } 80 | } 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /src/Simple.Testing.Framework/extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using Simple.Testing.ClientFramework; 7 | 8 | namespace Simple.Testing.Framework 9 | { 10 | public static class SpecificationExtensions 11 | { 12 | public static SpecificationToRun AsRunnable(this Specification specification) 13 | { 14 | return new SpecificationToRun(specification, null); 15 | } 16 | } 17 | static class DelegateExtensions 18 | { 19 | public static object InvokeIfNotNull(this Delegate d) 20 | { 21 | return d != null ? d.DynamicInvoke() : null; 22 | } 23 | } 24 | 25 | public static class IEnuerableExtensions 26 | { 27 | public static void ForEach(this IEnumerable sequence, Action action) 28 | { 29 | foreach (var item in sequence) action(item); 30 | } 31 | } 32 | 33 | public static class MethodInfoExtensions 34 | { 35 | public static object CallMethod(this MethodInfo methodInfo) 36 | { 37 | if (methodInfo.GetParameters().Length > 0) return null; 38 | var obj = Activator.CreateInstance(methodInfo.DeclaringType); 39 | var ret = methodInfo.Invoke(obj, null); 40 | return ret; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Simple.Testing.Runner/Options.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Options.cs 3 | // 4 | // Authors: 5 | // Jonathan Pryor 6 | // 7 | // Copyright (C) 2008 Novell (http://www.novell.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining 10 | // a copy of this software and associated documentation files (the 11 | // "Software"), to deal in the Software without restriction, including 12 | // without limitation the rights to use, copy, modify, merge, publish, 13 | // distribute, sublicense, and/or sell copies of the Software, and to 14 | // permit persons to whom the Software is furnished to do so, subject to 15 | // the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be 18 | // included in all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | // 28 | 29 | // Compile With: 30 | // gmcs -debug+ -d:TEST -langversion:linq -r:System.Core Options.cs 31 | 32 | // 33 | // A Getopt::Long-inspired option parsing library for C#. 34 | // 35 | // Mono.Documentation.Options is built upon a key/value table, where the 36 | // key is a option format string and the value is an Action 37 | // delegate that is invoked when the format string is matched. 38 | // 39 | // Option format strings: 40 | // BNF Grammar: ( name [=:]? ) ( '|' name [=:]? )+ 41 | // 42 | // Each '|'-delimited name is an alias for the associated action. If the 43 | // format string ends in a '=', it has a required value. If the format 44 | // string ends in a ':', it has an optional value. If neither '=' or ':' 45 | // is present, no value is supported. 46 | // 47 | // Options are extracted either from the current option by looking for 48 | // the option name followed by an '=' or ':', or is taken from the 49 | // following option IFF: 50 | // - The current option does not contain a '=' or a ':' 51 | // - The following option is not a registered named option 52 | // 53 | // The `name' used in the option format string does NOT include any leading 54 | // option indicator, such as '-', '--', or '/'. All three of these are 55 | // permitted/required on any named option. 56 | // 57 | // Option bundling is permitted so long as: 58 | // - '-' is used to start the option group 59 | // - all of the bundled options do not require values 60 | // - all of the bundled options are a single character 61 | // 62 | // This allows specifying '-a -b -c' as '-abc'. 63 | // 64 | // Option processing is disabled by specifying "--". All options after "--" 65 | // are returned by Options.Parse() unchanged and unprocessed. 66 | // 67 | // Unprocessed options are returned from Options.Parse(). 68 | // 69 | // Examples: 70 | // int verbose = 0; 71 | // Options p = new Options () 72 | // .Add ("v", (v) => ++verbose) 73 | // .Add ("name=|value=", (v) => Console.WriteLine (v)); 74 | // p.Parse (new string[]{"-v", "--v", "/v", "-name=A", "/name", "B", "extra"}) 75 | // .ToArray (); 76 | // 77 | // The above would parse the argument string array, and would invoke the 78 | // lambda expression three times, setting `verbose' to 3 when complete. 79 | // It would also print out "A" and "B" to standard output. 80 | // The returned arrray would contain the string "extra". 81 | // 82 | // C# 3.0 collection initializers are supported: 83 | // var p = new Options () { 84 | // { "h|?|help", (v) => ShowHelp () }, 85 | // }; 86 | // 87 | // System.ComponentModel.TypeConverter is also supported, allowing the use of 88 | // custom data types in the callback type; TypeConverter.ConvertFromString() 89 | // is used to convert the value option to an instance of the specified 90 | // type: 91 | // 92 | // var p = new Options () { 93 | // { "foo=", (Foo f) => Console.WriteLine (f.ToString ()) }, 94 | // }; 95 | // 96 | // Random other tidbits: 97 | // - Boolean options (those w/o '=' or ':' in the option format string) 98 | // are explicitly enabled if they are followed with '+', and explicitly 99 | // disabled if they are followed with '-': 100 | // string a = null; 101 | // var p = new Options () { 102 | // { "a", (s) => a = s }, 103 | // }; 104 | // p.Parse (new string[]{"-a"}); // sets v != null 105 | // p.Parse (new string[]{"-a+"}); // sets v != null 106 | // p.Parse (new string[]{"-a-"}); // sets v == null 107 | // 108 | 109 | using System; 110 | using System.Collections.Generic; 111 | using System.Collections.ObjectModel; 112 | using System.ComponentModel; 113 | using System.IO; 114 | using System.Text.RegularExpressions; 115 | 116 | namespace Simple.Testing.Runner { 117 | 118 | enum OptionValue { 119 | None, 120 | Optional, 121 | Required 122 | } 123 | 124 | public class Option { 125 | string prototype, description; 126 | Action action; 127 | string[] prototypes; 128 | OptionValue type; 129 | 130 | public Option (string prototype, string description, Action action) 131 | { 132 | this.prototype = prototype; 133 | this.prototypes = prototype.Split ('|'); 134 | this.description = description; 135 | this.action = action; 136 | this.type = GetOptionValue (); 137 | } 138 | 139 | public string Prototype { get { return prototype; } } 140 | public string Description { get { return description; } } 141 | public Action Action { get { return action; } } 142 | 143 | internal string[] Prototypes { get { return prototypes; } } 144 | internal OptionValue OptionValue { get { return type; } } 145 | 146 | OptionValue GetOptionValue () 147 | { 148 | foreach (string n in Prototypes) { 149 | if (n.IndexOf ('=') >= 0) 150 | return OptionValue.Required; 151 | if (n.IndexOf (':') >= 0) 152 | return OptionValue.Optional; 153 | } 154 | return OptionValue.None; 155 | } 156 | 157 | public override string ToString () 158 | { 159 | return Prototype; 160 | } 161 | } 162 | 163 | public class Options : Collection