Added unit testing project.

pull/5/head
Sean McArde 2023-07-24 12:58:19 -07:00 committed by Sean McArdle
parent 9478aa9bfc
commit 739ed9021c
5 changed files with 182 additions and 2 deletions

150
McRule.Tests/Filtering.cs Normal file
View File

@ -0,0 +1,150 @@
namespace McRule.Tests {
public class Filtering {
People[] things = new[] {
new People("Sean", "Confused", 35, new[] {"muggle"}),
new People("Sean", "Actor", 90, new[] {"muggle", "metallurgist"}),
new People("Bean", "Runt", 20, new[] {"muggle", "giant"}),
new People("Robin", "Comedian", 63, new[] {"muggle", "hilarious"}),
new People("Tim", "Enchantor", 999, new[] {"magical", "grumpy"}),
new People("Ragnar", "Viking", 25, new[] {"muggle", "grumpy"}),
new People("Lars", "Viking", 30, new[] {"muggle", "grumpy"}),
new People("Ferris", "Student", 17, new[] {"muggle"}),
};
public record People(string name, string kind, int number, string[] tags = null);
ExpressionPolicy notSean = new ExpressionPolicy {
Name = "Not named Sean",
Properties = new string[] { }, // Can't do anything with this yet
Rules = new List<ExpressionRule>
{
("People", "name", "!Sean").ToFilterRule(),
}
};
ExpressionPolicy eans = new ExpressionPolicy {
Name = "eans",
Properties = new string[] { }, // Can't do anything with this yet
Rules = new List<ExpressionRule>
{
("People", "name", "*ean").ToFilterRule(),
("People", "name", "~*EAN").ToFilterRule(),
},
RuleOperator = PredicateExpressionPolicyExtensions.RuleOperator.And
};
ExpressionPolicy youngens = new ExpressionPolicy {
Name = "Young folk",
Properties = new string[] { }, // Can't do anything with this yet
Rules = new List<ExpressionRule>
{
("People", "number", ">=17").ToFilterRule(),
("People", "number", "<30").ToFilterRule(),
},
RuleOperator = PredicateExpressionPolicyExtensions.RuleOperator.And
};
ExpressionPolicy vikings = new ExpressionPolicy {
Name = "Vikings",
Rules = new List<ExpressionRule>
{
("People", "kind", "~viking").ToFilterRule(),
},
RuleOperator = PredicateExpressionPolicyExtensions.RuleOperator.And
};
ExpressionPolicy muggles = new ExpressionPolicy {
Name = "Non-magic folk",
Rules = new List<ExpressionRule>
{
("People", "tags", "muggle").ToFilterRule(),
},
RuleOperator = PredicateExpressionPolicyExtensions.RuleOperator.And
};
[SetUp]
public void Setup() {
}
[Test]
public void NegativeStringMatch() {
var filter = notSean.GetExpression<People>()?.Compile();
var folks = things.Where(filter);
Assert.Null(folks.FirstOrDefault(x => x.name == "Sean"));
}
[Test]
public void EndsWith() {
// Filter should match on people who's name ends in 'ean',
// and case insensitive ends with 'EAN'.
var filter = eans.GetExpression<People>()?.Compile();
var folks = things.Where(filter);
Assert.NotNull(folks);
Assert.IsTrue(folks.All(x => x.name.EndsWith("ean")));
}
[Test]
public void CombineTwoExpressionsIntoCollection() {
// Combine two different filters with an And
var filter = new ExpressionRuleCollection() {
Rules = new[] {
youngens, vikings
},
RuleOperator = PredicateExpressionPolicyExtensions.RuleOperator.And
}?.GetExpression<People>()?.Compile();
var folks = things.Where(filter);
// Match should be exclusive enough to only include Ragnar
Assert.NotNull(folks);
Assert.IsTrue(folks.Count() == 1);
Assert.IsTrue(folks.FirstOrDefault()?.name == "Ragnar");
// Process both expressions separately to verify they
// have different results.
filter = youngens.GetExpression<People>()?.Compile();
folks = things.Where(filter);
Assert.IsTrue(folks.Count() > 1);
filter = vikings.GetExpression<People>()?.Compile();
folks = things.Where(filter);
Assert.IsTrue(folks.Count() > 1);
// Original compound filter with an Or predicate
filter = new ExpressionRuleCollection() {
Rules = new[] {
youngens, vikings
},
RuleOperator = PredicateExpressionPolicyExtensions.RuleOperator.Or
}?.GetExpression<People>()?.Compile();
folks = things.Where(filter);
Assert.IsTrue(folks.Count() > 1);
// Should include Vikings by kind and Student by number
Assert.NotNull(folks.Where(x => x.kind == "Viking"));
Assert.NotNull(folks.Where(x => x.kind == "Student"));
}
[Test]
public void YoungPeople() {
var filter = youngens.GetPredicateExpression<People>()?.Compile();
var folks = things.Where(filter);
Assert.NotNull(folks);
Assert.IsTrue(folks.All(x => x.number >= 17 && x.number < 30));
}
[Test]
public void MugglesByTag() {
var filter = muggles.GetExpression<People>()?.Compile();
var folks = things.Where(filter);
Assert.NotNull(folks);
Assert.IsTrue(folks.All(x => x.tags.Contains("muggle")));
}
}
}

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="NUnit.Analyzers" Version="3.3.0" />
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\McRule\McRule.csproj" />
</ItemGroup>
</Project>

1
McRule.Tests/Usings.cs Normal file
View File

@ -0,0 +1 @@
global using NUnit.Framework;

View File

@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "McRule.Tests", "McRule.Tests\McRule.Tests.csproj", "{15DC72B8-E535-4E1D-82FA-A78BA540F0A4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -26,6 +28,10 @@ Global
{0E6DF52C-D171-4E84-8D6D-BB580DF35E51}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0E6DF52C-D171-4E84-8D6D-BB580DF35E51}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E6DF52C-D171-4E84-8D6D-BB580DF35E51}.Release|Any CPU.Build.0 = Release|Any CPU
{15DC72B8-E535-4E1D-82FA-A78BA540F0A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{15DC72B8-E535-4E1D-82FA-A78BA540F0A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{15DC72B8-E535-4E1D-82FA-A78BA540F0A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{15DC72B8-E535-4E1D-82FA-A78BA540F0A4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -88,7 +88,7 @@ var thePolicy = new ExpressionPolicy {
Properties = new string[] { }, // Can't do anything with this yet
Rules = new List<ExpressionRule>
{
("Thing", "Name", "!Sean").ToFilterRule(),
("Thing", "name", "!Sean").ToFilterRule(),
}
};
@ -97,7 +97,7 @@ filter.Dump();
new[] { new Thing("Sean", "Confused"), new Thing("Tim", "Enchantor") }.Where(filter.Compile()).Dump();
public record Thing(string Name, string Kind);
public record Thing(string name, string kind, string[] tags = null);
record User(string first, string last, string workPhone, string homePhone, string workAddress, string agency, string[] tags = null);