diff --git a/PoweredSoft.DynamicQuery.Test/AggregateTests.cs b/PoweredSoft.DynamicQuery.Test/AggregateTests.cs new file mode 100644 index 0000000..ae68e77 --- /dev/null +++ b/PoweredSoft.DynamicQuery.Test/AggregateTests.cs @@ -0,0 +1,116 @@ +using PoweredSoft.DynamicQuery.Core; +using PoweredSoft.DynamicQuery.Test.Mock; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Xunit; + +namespace PoweredSoft.DynamicQuery.Test +{ + + public class AggregateTests + { + [Fact] + public void WithoutGrouping() + { + MockContextFactory.SeedAndTestContextFor("AggregateTests_WithoutGrouping", TestSeeders.SimpleSeedScenario, ctx => + { + var shouldResult = ctx.OrderItems + .GroupBy(t => true) + .Select(t => new + { + Count = t.Count(), + ItemQuantityAverage = t.Average(t2 => t2.Quantity), + ItemQuantitySum = t.Sum(t2 => t2.Quantity), + AvgOfPrice = t.Average(t2 => t2.PriceAtTheTime) + }) + .First(); + + // query handler that is empty should be the same as running to list. + var criteria = new QueryCriteria() + { + Aggregates = new List + { + new Aggregate { Type = AggregateType.Count }, + new Aggregate { Type = AggregateType.Avg, Path = "Quantity" }, + new Aggregate { Type = AggregateType.Sum, Path = "Quantity" }, + new Aggregate { Type = AggregateType.Avg, Path = "PriceAtTheTime"} + } + }; + + var queryHandler = new QueryHandler(); + var result = queryHandler.Execute(ctx.OrderItems, criteria); + + var aggCount = result.Aggregates.First(t => t.Type == AggregateType.Count); + var aggItemQuantityAverage = result.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "Quantity"); + var aggItemQuantitySum = result.Aggregates.First(t => t.Type == AggregateType.Sum && t.Path == "Quantity"); + var aggAvgOfPrice = result.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "PriceAtTheTime"); + Assert.Equal(shouldResult.Count, aggCount.Value); + Assert.Equal(shouldResult.ItemQuantityAverage, aggItemQuantityAverage.Value); + Assert.Equal(shouldResult.ItemQuantitySum, aggItemQuantitySum.Value); + Assert.Equal(shouldResult.AvgOfPrice, aggAvgOfPrice.Value); + }); + } + + [Fact] + public void WithGrouping() + { + MockContextFactory.SeedAndTestContextFor("AggregateTests_WithGrouping", TestSeeders.SimpleSeedScenario, ctx => + { + var shouldResults = ctx.OrderItems + .GroupBy(t => t.Order.CustomerId) + .Select(t => new + { + GroupValue = t.Key, + Count = t.Count(), + ItemQuantityAverage = t.Average(t2 => t2.Quantity), + ItemQuantitySum = t.Sum(t2 => t2.Quantity), + AvgOfPrice = t.Average(t2 => t2.PriceAtTheTime) + }) + .ToList(); + + // query handler that is empty should be the same as running to list. + var criteria = new QueryCriteria() + { + Groups = new List + { + new Group { Path = "Order.CustomerId" } + }, + Aggregates = new List + { + new Aggregate { Type = AggregateType.Count }, + new Aggregate { Type = AggregateType.Avg, Path = "Quantity" }, + new Aggregate { Type = AggregateType.Sum, Path = "Quantity" }, + new Aggregate { Type = AggregateType.Avg, Path = "PriceAtTheTime"} + } + }; + + var queryHandler = new QueryHandler(); + var result = queryHandler.Execute(ctx.OrderItems, criteria); + var groups = result.Data.Cast().ToList(); + + // validate group and aggregates of groups. + Assert.Equal(groups.Count, shouldResults.Count); + Assert.All(groups, g => + { + var index = groups.IndexOf(g); + var shouldResult = shouldResults[index]; + + // validate the group value. + Assert.Equal(g.GroupValue, shouldResult.GroupValue); + + // validate the group aggregates. + var aggCount = g.Aggregates.First(t => t.Type == AggregateType.Count); + var aggItemQuantityAverage = g.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "Quantity"); + var aggItemQuantitySum = g.Aggregates.First(t => t.Type == AggregateType.Sum && t.Path == "Quantity"); + var aggAvgOfPrice = g.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "PriceAtTheTime"); + Assert.Equal(shouldResult.Count, aggCount.Value); + Assert.Equal(shouldResult.ItemQuantityAverage, aggItemQuantityAverage.Value); + Assert.Equal(shouldResult.ItemQuantitySum, aggItemQuantitySum.Value); + Assert.Equal(shouldResult.AvgOfPrice, aggAvgOfPrice.Value); + }); + }); + } + } +} diff --git a/README.md b/README.md index 9d4cdb6..cfc18aa 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,13 @@ Criteria must implement the following interfaces Object | Interface | Implementation | Example | Description -----------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------------|----------------------------------------------------------------------|-------------------------------------------- Query Criteria | [interface](../master/PoweredSoft.DynamicQuery.Core/IQueryCriteria.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/QueryCriteria.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/CriteriaTests.cs#L13) | Wraps the query parameters -Paging | [interface](../master/PoweredSoft.DynamicQuery.Core/IQueryCriteria.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/QueryCriteria.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/CriteriaTests.cs#L29) | Paging support +Paging | [interface](../master/PoweredSoft.DynamicQuery.Core/IQueryCriteria.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/QueryCriteria.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/CriteriaTests.cs#L29) | Paging support Filter | [interface](../master/PoweredSoft.DynamicQuery.Core/IFilter.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Filter.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/FilterTests.cs#L22) | Represent a filter to be executed Simple Filter | [interface](../master/PoweredSoft.DynamicQuery.Core/ISimpleFilter.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Filter.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/FilterTests.cs#L40) | Represent a simple filter to be executed Composite Filter | [interface](../master/PoweredSoft.DynamicQuery.Core/ICompositeFilter.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Filter.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/FilterTests.cs#L68) | Represent a composite filter to be executed Sort | [interface](../master/PoweredSoft.DynamicQuery.Core/ISort.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Sort.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/SortTests.cs#L15) | Represent a sort to be executed Group | [interface](../master/PoweredSoft.DynamicQuery.Core/IGroup.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Group.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/GroupTests.cs) | Represent a group to be executed -Aggregate | [interface](../master/PoweredSoft.DynamicQuery.Core/IAggregate.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Aggregate.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/TBT.md) | Represent an aggregate to be executed +Aggregate | [interface](../master/PoweredSoft.DynamicQuery.Core/IAggregate.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Aggregate.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/AggregateTests.cs) | Represent an aggregate to be executed ### Sample