Skip to content

Commit 578ccc3

Browse files
committed
first cut at supporting NUnit 4.x Constraints
1 parent 1e9b378 commit 578ccc3

14 files changed

+1755
-0
lines changed

XMLUnit.NET.sln

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XMLUnit.Placeholders.Tests"
2929
EndProject
3030
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{AEB02F96-2A15-4740-84CB-6F7E36F85062}"
3131
EndProject
32+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XMLUnit.NUnit4.Constraints.Test", "src\tests\net-constraints-nunit4\XMLUnit.NUnit4.Constraints.Test.csproj", "{A4710B49-EB5D-4E6E-A515-AE73AC9773CF}"
33+
EndProject
34+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XMLUnit.NUnit4.Constraints", "src\main\net-constraints-nunit4\XMLUnit.NUnit4.Constraints.csproj", "{9E6EA8DE-F1E9-4DC0-8E9C-EDCAF0E44FA7}"
35+
EndProject
3236
Global
3337
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3438
Debug|Any CPU = Debug|Any CPU
@@ -59,6 +63,14 @@ Global
5963
{97290BD0-CCF0-48CF-95F2-B1A9F6C3EE9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
6064
{97290BD0-CCF0-48CF-95F2-B1A9F6C3EE9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
6165
{97290BD0-CCF0-48CF-95F2-B1A9F6C3EE9F}.Release|Any CPU.Build.0 = Release|Any CPU
66+
{A4710B49-EB5D-4E6E-A515-AE73AC9773CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
67+
{A4710B49-EB5D-4E6E-A515-AE73AC9773CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
68+
{A4710B49-EB5D-4E6E-A515-AE73AC9773CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
69+
{A4710B49-EB5D-4E6E-A515-AE73AC9773CF}.Release|Any CPU.Build.0 = Release|Any CPU
70+
{9E6EA8DE-F1E9-4DC0-8E9C-EDCAF0E44FA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
71+
{9E6EA8DE-F1E9-4DC0-8E9C-EDCAF0E44FA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
72+
{9E6EA8DE-F1E9-4DC0-8E9C-EDCAF0E44FA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
73+
{9E6EA8DE-F1E9-4DC0-8E9C-EDCAF0E44FA7}.Release|Any CPU.Build.0 = Release|Any CPU
6274
EndGlobalSection
6375
GlobalSection(SolutionProperties) = preSolution
6476
HideSolutionNode = FALSE
@@ -67,6 +79,7 @@ Global
6779
{9BF85579-75BF-4D44-953A-46FAFCD814C0} = {AEB02F96-2A15-4740-84CB-6F7E36F85062}
6880
{33760FFE-9F43-46BE-8F64-ED34AE6B798C} = {AEB02F96-2A15-4740-84CB-6F7E36F85062}
6981
{97290BD0-CCF0-48CF-95F2-B1A9F6C3EE9F} = {AEB02F96-2A15-4740-84CB-6F7E36F85062}
82+
{A4710B49-EB5D-4E6E-A515-AE73AC9773CF} = {AEB02F96-2A15-4740-84CB-6F7E36F85062}
7083
EndGlobalSection
7184
GlobalSection(ExtensibilityGlobals) = postSolution
7285
SolutionGuid = {62909FEB-64D4-42B9-845A-E7E1AAD5F331}

appveyor.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ for:
3939
test_script:
4040
- dotnet test src/tests/net-core/XMLUnit.Core.Tests.csproj
4141
- dotnet test src/tests/net-constraints-nunit3/XMLUnit.NUnit3.Constraints.Test.csproj
42+
- dotnet test src/tests/net-constraints-nunit4/XMLUnit.NUnit4.Constraints.Test.csproj
4243
- dotnet test src/tests/net-placeholders/XMLUnit.Placeholders.Tests.csproj
4344

4445
install:
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
This file is licensed to You under the Apache License, Version 2.0
3+
(the "License"); you may not use this file except in compliance with
4+
the License. You may obtain a copy of the License at
5+
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
*/
14+
using System.Reflection;
15+
using System.Runtime.CompilerServices;
16+
17+
[assembly: AssemblyTitleAttribute("XMLUnit Constraints for NUnit 4.x")]
18+
[assembly: AssemblyDescription("NUnit 4.x Constraints Classes of XMLUnit for .NET")]
19+
[assembly: InternalsVisibleTo("xmlunit-nunit4-constraints.tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100fdec9d5858956ff10ff9cf39935441a7d4a216475a467e951ddd8fcce0b74443696680a6cfb58f8b1d96166acb76f9eae0431a223cecb30e224c21f30e57c457747f6ba176e6c22f48e105b200b458509b6de815cccdfc9ebe59ae4024c4b8659d2f2fcb65b1688f8327b10c96ed7e5f536ba6a1978ae86aca438439efbd6cb6")]
20+
[assembly: AssemblyProduct("XMLUnit.NET Constraints for NUnit 4")]
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
/*
2+
This file is licensed to You under the Apache License, Version 2.0
3+
(the "License"); you may not use this file except in compliance with
4+
the License. You may obtain a copy of the License at
5+
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
*/
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.Linq;
18+
using System.Xml;
19+
using NUnit.Framework.Constraints;
20+
using Org.XmlUnit.Builder;
21+
using Org.XmlUnit.Diff;
22+
23+
namespace Org.XmlUnit.Constraints {
24+
25+
/// <summary>
26+
/// Constraint that compares two XML sources with each other.
27+
/// </summary>
28+
/// <remarks>
29+
/// <para>
30+
/// since XMLUnit 2.11.0
31+
/// </para>
32+
/// </remarks>
33+
public class CompareConstraint : Constraint, IDifferenceEngineConfigurer<CompareConstraint> {
34+
35+
private readonly DiffBuilder diffBuilder;
36+
private ComparisonResult checkFor;
37+
private bool formatXml;
38+
private IComparisonFormatter comparisonFormatter = new DefaultComparisonFormatter();
39+
40+
private CompareConstraint(object control) {
41+
diffBuilder = DiffBuilder.Compare(control);
42+
}
43+
44+
/// <summary>
45+
/// Create a CompareConstraint which compares the
46+
/// test-Object with the given control Object for identity.
47+
/// </summary>
48+
public static CompareConstraint IsIdenticalTo(object control) {
49+
return new CompareConstraint(control).CheckForIdentical();
50+
}
51+
52+
/// <summary>
53+
/// Create a CompareConstraint which compares the
54+
/// test-Object with the given control Object for similarity.
55+
/// </summary>
56+
/// <remarks>
57+
/// <para>
58+
/// Example for Similar: The XML node
59+
/// "&lt;a&gt;Text&lt;/a&gt;" and
60+
/// "&lt;a&gt;&lt;![CDATA[Text]]&gt;&lt;/a&gt;" are
61+
/// similar and the Test will not fail.
62+
/// </para>
63+
/// </remarks>
64+
public static CompareConstraint IsSimilarTo(object control) {
65+
return new CompareConstraint(control).CheckForSimilar();
66+
}
67+
68+
public override string Description
69+
{
70+
get
71+
{
72+
return "is " + (checkFor == ComparisonResult.EQUAL ? "equal" : "similar") + " to the control document";
73+
}
74+
}
75+
76+
private CompareConstraint CheckForSimilar() {
77+
diffBuilder.CheckForSimilar();
78+
checkFor = ComparisonResult.SIMILAR;
79+
return this;
80+
}
81+
82+
private CompareConstraint CheckForIdentical() {
83+
diffBuilder.CheckForIdentical();
84+
checkFor = ComparisonResult.EQUAL;
85+
return this;
86+
}
87+
88+
/// <summary>
89+
/// Ignore whitespace differences.
90+
/// </summary>
91+
public CompareConstraint IgnoreWhitespace() {
92+
formatXml = true;
93+
diffBuilder.IgnoreWhitespace();
94+
return this;
95+
}
96+
97+
/// <summary>
98+
/// Ignore element content whitespace differences.
99+
/// </summary>
100+
/// <remarks>
101+
/// <para>
102+
/// since XMLUnit 2.6.0
103+
/// </para>
104+
/// </remarks>
105+
public CompareConstraint IgnoreElementContentWhitespace() {
106+
diffBuilder.IgnoreElementContentWhitespace();
107+
return this;
108+
}
109+
110+
/// <summary>
111+
/// Normalize whitespace before comparing.
112+
/// </summary>
113+
public CompareConstraint NormalizeWhitespace() {
114+
formatXml = true;
115+
diffBuilder.NormalizeWhitespace();
116+
return this;
117+
}
118+
119+
/// <summary>
120+
/// Ignore comments.
121+
/// </summary>
122+
public CompareConstraint IgnoreComments()
123+
{
124+
diffBuilder.IgnoreComments();
125+
return this;
126+
}
127+
128+
/// <summary>
129+
/// Ignore comments.
130+
/// </summary>
131+
/// <remarks>
132+
/// <para>
133+
/// since XMLUnit 2.5.0
134+
/// </para>
135+
/// </remarks>
136+
/// <param name="xsltVersion">use this version for the stylesheet</param>
137+
public CompareConstraint IgnoreCommentsUsingXSLTVersion(string xsltVersion)
138+
{
139+
diffBuilder.IgnoreCommentsUsingXSLTVersion(xsltVersion);
140+
return this;
141+
}
142+
143+
/// <summary>
144+
/// Use the given <see cref="INodeMatcher"/> when comparing.
145+
/// </summary>
146+
/// <param name="nodeMatcher">INodeMatcher to use</param>
147+
public CompareConstraint WithNodeMatcher(INodeMatcher nodeMatcher) {
148+
diffBuilder.WithNodeMatcher(nodeMatcher);
149+
return this;
150+
}
151+
152+
/// <summary>
153+
/// Use the given <see cref="DifferenceEvaluator"/> when comparing.
154+
/// </summary>
155+
/// <param name="differenceEvaluator">DifferenceEvaluator to use</param>
156+
public CompareConstraint WithDifferenceEvaluator(DifferenceEvaluator differenceEvaluator)
157+
{
158+
diffBuilder.WithDifferenceEvaluator(differenceEvaluator);
159+
return this;
160+
}
161+
162+
/// <summary>
163+
/// Use the given <see cref="ComparisonListener"/>s when comparing.
164+
/// </summary>
165+
/// <param name="comparisonListeners">ComparisonListeners to use</param>
166+
public CompareConstraint WithComparisonListeners(params ComparisonListener[] comparisonListeners)
167+
{
168+
diffBuilder.WithComparisonListeners(comparisonListeners);
169+
return this;
170+
}
171+
172+
/// <summary>
173+
/// Use the given <see cref="ComparisonListener"/>s as difference listeners when comparing.
174+
/// </summary>
175+
/// <param name="comparisonListeners">ComparisonListeners to use</param>
176+
public CompareConstraint WithDifferenceListeners(params ComparisonListener[] comparisonListeners)
177+
{
178+
diffBuilder.WithDifferenceListeners(comparisonListeners);
179+
return this;
180+
}
181+
182+
/// <summary>
183+
/// Use a custom Formatter for the Error Messages. The defaultFormatter is DefaultComparisonFormatter.
184+
/// </summary>
185+
public CompareConstraint WithComparisonFormatter(IComparisonFormatter comparisonFormatter) {
186+
this.comparisonFormatter = comparisonFormatter;
187+
return this;
188+
}
189+
190+
/// <summary>
191+
/// Registers a filter for attributes.
192+
/// </summary>
193+
/// <remarks>
194+
/// <para>
195+
/// Only attributes for which the predicate returns true are
196+
/// part of the comparison. By default all attributes are
197+
/// considered.
198+
/// </para>
199+
/// <para>
200+
/// The "special" namespace, namespace-location and
201+
/// schema-instance-type attributes can not be ignored this way.
202+
/// If you want to suppress comparison of them you'll need to
203+
/// implement <see cref="DifferenceEvaluator"/>
204+
/// </para>
205+
/// </remarks>
206+
public CompareConstraint WithAttributeFilter(Predicate<XmlAttribute> attributeFilter) {
207+
diffBuilder.WithAttributeFilter(attributeFilter);
208+
return this;
209+
}
210+
211+
/// <summary>
212+
/// Registers a filter for nodes.
213+
/// </summary>
214+
/// <remarks>
215+
/// <para>
216+
/// Only nodes for which the predicate returns true are part
217+
/// of the comparison. By default nodes that are neither
218+
/// document types nor XML declarations are considered.
219+
/// </para>
220+
/// </remarks>
221+
public CompareConstraint WithNodeFilter(Predicate<XmlNode> nodeFilter) {
222+
diffBuilder.WithNodeFilter(nodeFilter);
223+
return this;
224+
}
225+
226+
/// <summary>
227+
/// Establish a namespace context mapping from prefix to URI
228+
/// that will be used in Comparison.Detail.XPath.
229+
/// </summary>
230+
/// <remarks>
231+
/// Without a namespace context (or with an empty context) the
232+
/// XPath expressions will only use local names for elements and
233+
/// attributes.
234+
/// </remarks>
235+
public CompareConstraint WithNamespaceContext(IDictionary<string, string> ctx) {
236+
diffBuilder.WithNamespaceContext(ctx);
237+
return this;
238+
}
239+
240+
/// <summary>
241+
/// Throws an exception as you the ComparisonController is
242+
/// completely determined by the factory method used.
243+
/// </summary>
244+
/// <remarks>
245+
/// <para>
246+
/// since XMLUnit 2.5.1
247+
/// </para>
248+
/// </remarks>
249+
public CompareConstraint WithComparisonController(ComparisonController cc)
250+
{
251+
throw new NotImplementedException("Can't set ComparisonController with CompareConstraint");
252+
}
253+
254+
/// <inheritdoc/>
255+
public override ConstraintResult ApplyTo<TActual>(TActual actual) {
256+
if (checkFor == ComparisonResult.EQUAL) {
257+
diffBuilder.WithComparisonController(ComparisonControllers.StopWhenSimilar);
258+
} else if (checkFor == ComparisonResult.SIMILAR) {
259+
diffBuilder.WithComparisonController(ComparisonControllers.StopWhenDifferent);
260+
}
261+
262+
Diff.Diff diffResult = diffBuilder.WithTest(actual).Build();
263+
264+
return new CompareConstraintResult(this, actual, diffResult);
265+
}
266+
267+
/// <summary>
268+
/// Result of a CompareConstraint.
269+
/// </summary>
270+
public class CompareConstraintResult : ConstraintResult {
271+
private readonly CompareConstraint constraint;
272+
private readonly Diff.Diff diffResult;
273+
274+
/// <summary>
275+
/// Creates the result.
276+
/// </summary>
277+
public CompareConstraintResult(CompareConstraint constraint, object actualValue, Diff.Diff diffResult)
278+
: base(constraint, actualValue, !diffResult.HasDifferences()) {
279+
this.constraint = constraint;
280+
this.diffResult = diffResult;
281+
}
282+
283+
/// <inheritdoc/>
284+
public override void WriteMessageTo(MessageWriter writer) {
285+
Comparison c = diffResult.Differences.First().Comparison;
286+
writer.WriteMessageLine(constraint.comparisonFormatter.GetDescription(c));
287+
if (diffResult.TestSource.SystemId != null
288+
|| diffResult.ControlSource.SystemId != null)
289+
{
290+
writer.WriteMessageLine(string.Format("comparing {0} to {1}",
291+
diffResult.TestSource.SystemId,
292+
diffResult.ControlSource.SystemId));
293+
}
294+
writer.DisplayDifferences(GetDetails(c.ControlDetails, c.Type),
295+
GetDetails(c.TestDetails, c.Type));
296+
}
297+
298+
private string GetDetails(Comparison.Detail detail, ComparisonType type) {
299+
return constraint.comparisonFormatter.GetDetails(detail, type, constraint.formatXml);
300+
}
301+
}
302+
}
303+
}

0 commit comments

Comments
 (0)