Skip to content

Commit

Permalink
Increase mutation score (#1211)
Browse files Browse the repository at this point in the history
Increase mutation score
  • Loading branch information
jnyrup committed Dec 30, 2019
2 parents 4607f79 + c194c75 commit 503a453
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 16 deletions.
26 changes: 10 additions & 16 deletions Src/FluentAssertions/Primitives/StringAssertions.cs
Expand Up @@ -276,23 +276,20 @@ public AndConstraint<StringAssertions> MatchRegex([RegexPattern] string regularE
.BecauseOf(because, becauseArgs)
.FailWith("Expected {context:string} to match regex {0}{reason}, but it was <null>.", regularExpression);

bool isMatch = false;
try
{
isMatch = Regex.IsMatch(Subject, regularExpression);
Execute.Assertion
.ForCondition(Regex.IsMatch(Subject, regularExpression))
.BecauseOf(because, becauseArgs)
.UsingLineBreaks
.FailWith("Expected {context:string} to match regex {0}{reason}, but {1} does not match.", regularExpression, Subject);
}
catch (ArgumentException)
{
Execute.Assertion
.FailWith("Cannot match {context:string} against {0} because it is not a valid regular expression.", regularExpression);
}

Execute.Assertion
.ForCondition(isMatch)
.BecauseOf(because, becauseArgs)
.UsingLineBreaks
.FailWith("Expected {context:string} to match regex {0}{reason}, but {1} does not match.", regularExpression, Subject);

return new AndConstraint<StringAssertions>(this);
}

Expand All @@ -319,23 +316,20 @@ public AndConstraint<StringAssertions> NotMatchRegex([RegexPattern] string regul
.BecauseOf(because, becauseArgs)
.FailWith("Expected {context:string} to not match regex {0}{reason}, but it was <null>.", regularExpression);

bool isMatch = false;
try
{
isMatch = Regex.IsMatch(Subject, regularExpression);
Execute.Assertion
.ForCondition(!Regex.IsMatch(Subject, regularExpression))
.BecauseOf(because, becauseArgs)
.UsingLineBreaks
.FailWith("Did not expect {context:string} to match regex {0}{reason}, but {1} matches.", regularExpression, Subject);
}
catch (ArgumentException)
{
Execute.Assertion.FailWith("Cannot match {context:string} against {0} because it is not a valid regular expression.",
regularExpression);
}

Execute.Assertion
.ForCondition(!isMatch)
.BecauseOf(because, becauseArgs)
.UsingLineBreaks
.FailWith("Did not expect {context:string} to match regex {0}{reason}, but {1} matches.", regularExpression, Subject);

return new AndConstraint<StringAssertions>(this);
}

Expand Down
36 changes: 36 additions & 0 deletions Tests/Shared.Specs/AsyncFunctionExceptionAssertionSpecs.cs
Expand Up @@ -1032,6 +1032,24 @@ public void When_wait_time_is_negative_for_async_func_executed_with_wait_it_shou
.WithMessage("* value of waitTime must be non-negative*");
}

[Fact]
public void When_wait_time_is_zero_for_async_func_executed_with_wait_it_should_not_throw()
{
// Arrange
var waitTime = 0.Milliseconds();
var pollInterval = 10.Milliseconds();

var clock = new FakeClock();
var asyncObject = new AsyncClass();
Func<Task> someFunc = () => asyncObject.SucceedAsync();

// Act
Action act = () => someFunc.Should(clock).NotThrowAfter(waitTime, pollInterval);

// Assert
act.Should().NotThrow();
}

[Fact]
public void When_poll_interval_is_negative_for_async_func_executed_with_wait_it_should_throw()
{
Expand All @@ -1050,6 +1068,24 @@ public void When_poll_interval_is_negative_for_async_func_executed_with_wait_it_
.WithMessage("* value of pollInterval must be non-negative*");
}

[Fact]
public void When_poll_interval_is_zero_for_async_func_executed_with_wait_it_should_not_throw()
{
// Arrange
var waitTime = 10.Milliseconds();
var pollInterval = 0.Milliseconds();

var clock = new FakeClock();
var asyncObject = new AsyncClass();
Func<Task> someFunc = () => asyncObject.SucceedAsync();

// Act
Action act = () => someFunc.Should(clock).NotThrowAfter(waitTime, pollInterval);

// Assert
act.Should().NotThrow();
}

[Fact]
public void
When_no_exception_should_be_thrown_for_async_func_executed_with_wait_after_wait_time_but_it_was_it_should_throw()
Expand Down
26 changes: 26 additions & 0 deletions Tests/Shared.Specs/CollectionAssertionSpecs.cs
Expand Up @@ -197,6 +197,32 @@ public void When_collection_count_is_matched_against_a_predicate_and_collection_
"Expected collection to contain (c < 3) items because we want to test the behaviour with a null subject, but found <null>.");
}

[Fact]
public void When_collection_count_is_matched_against_a_predicate_it_should_not_throw()
{
// Arrange
IEnumerable collection = new[] { 1, 2, 3 };

// Act
Action act = () => collection.Should().HaveCount(c => c % 2 == 1);

// Assert
act.Should().NotThrow();
}

[Fact]
public void When_collection_count_is_matched_against_a_predicate_it_should_throw()
{
// Arrange
IEnumerable collection = new[] { 1, 2, 3 };

// Act
Action act = () => collection.Should().HaveCount(c => c % 2 == 0);

// Assert
act.Should().Throw<XunitException>();
}

[Fact]
public void When_counting_nongeneric_enumerable_it_should_enumerate()
{
Expand Down
21 changes: 21 additions & 0 deletions Tests/Shared.Specs/DateTimeOffsetValueFormatterSpecs.cs
Expand Up @@ -73,6 +73,27 @@ public void When_date_is_not_relevant_it_should_not_be_included_in_the_output()
result.Should().Be("<08:20:01>");
}

[InlineData("0001-01-02 04:05:06", "<0001-01-02 04:05:06>")]
[InlineData("0001-02-01 04:05:06", "<0001-02-01 04:05:06>")]
[InlineData("0002-01-01 04:05:06", "<0002-01-01 04:05:06>")]
[InlineData("0001-02-02 04:05:06", "<0001-02-02 04:05:06>")]
[InlineData("0002-01-02 04:05:06", "<0002-01-02 04:05:06>")]
[InlineData("0002-02-01 04:05:06", "<0002-02-01 04:05:06>")]
[InlineData("0002-02-02 04:05:06", "<0002-02-02 04:05:06>")]
[Theory]
public void When_date_is_relevant_it_should_be_included_in_the_output(string actual, string expected)
{
// Arrange
var formatter = new DateTimeOffsetValueFormatter();
var value = DateTime.Parse(actual, CultureInfo.InvariantCulture);

// Act
string result = formatter.Format(value, new FormattingContext(), null);

// Assert
result.Should().Be(expected);
}

[Fact]
public void When_a_full_date_and_time_is_specified_all_parts_should_be_included_in_the_output()
{
Expand Down
36 changes: 36 additions & 0 deletions Tests/Shared.Specs/GenericDictionaryAssertionSpecs.cs
Expand Up @@ -1525,6 +1525,24 @@ public void When_a_dictionary_contains_a_list_of_keys_it_should_throw_with_clear
"Expected dictionary {[1, One], [2, Two]} to not contain key {2, 3} because we do, but found {2}.");
}

[Fact]
public void When_a_dictionary_contains_exactly_one_of_the_keys_it_should_throw_with_clear_explanation()
{
// Arrange
var dictionary = new Dictionary<int, string>
{
[1] = "One",
[2] = "Two"
};

// Act
Action act = () => dictionary.Should().NotContainKeys(new[] { 2 }, "because {0}", "we do");

// Assert
act.Should().Throw<XunitException>().WithMessage(
"Expected dictionary {[1, One], [2, Two]} to not contain key 2 because we do.");
}

[Fact]
public void When_the_noncontents_of_a_dictionary_are_checked_against_an_empty_list_of_keys_it_should_throw_clear_explanation()
{
Expand Down Expand Up @@ -1763,6 +1781,24 @@ public void When_dictionary_does_not_contain_multiple_values_that_is_not_in_the_
act.Should().NotThrow<XunitException>();
}

[Fact]
public void When_a_dictionary_contains_a_exactly_one_of_the_values_it_should_throw_with_clear_explanation()
{
// Arrange
var dictionary = new Dictionary<int, string>
{
[1] = "One",
[2] = "Two"
};

// Act
Action act = () => dictionary.Should().NotContainValues(new[] { "Two" }, "because {0}", "we do");

// Assert
act.Should().Throw<XunitException>().WithMessage(
"Expected dictionary {[1, One], [2, Two]} to not contain value \"Two\" because we do.");
}

[Fact]
public void When_a_dictionary_contains_a_number_of_values_it_should_throw_with_clear_explanation()
{
Expand Down
26 changes: 26 additions & 0 deletions Tests/Shared.Specs/ReferenceTypeAssertionsSpecs.cs
Expand Up @@ -229,6 +229,32 @@ public void When_object_is_not_of_the_unexpected_open_generic_type_it_should_not
action.Should().NotThrow();
}

[Fact]
public void When_generic_object_is_not_of_the_unexpected_type_it_should_not_throw()
{
// Arrange
var aList = new System.Collections.Generic.List<string>();

// Act
Action action = () => aList.Should().NotBeOfType<string>();

// Assert
action.Should().NotThrow();
}

[Fact]
public void When_non_generic_object_is_not_of_the_unexpected_open_generic_type_it_should_not_throw()
{
// Arrange
var aString = "blah";

// Act
Action action = () => aString.Should().NotBeOfType(typeof(System.Collections.Generic.Dictionary<,>));

// Assert
action.Should().NotThrow();
}

[Fact]
public void When_asserting_object_is_not_of_type_and_it_is_null_it_should_throw()
{
Expand Down
71 changes: 71 additions & 0 deletions Tests/Shared.Specs/StringAssertionSpecs.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using FluentAssertions.Execution;
using Xunit;
using Xunit.Sdk;

Expand Down Expand Up @@ -458,6 +459,19 @@ public void When_a_string_does_match_the_equivalent_of_a_wildcard_pattern_it_sho
act.Should().NotThrow();
}

[Fact]
public void When_a_string_with_newline_matches_the_equivalent_of_a_wildcard_pattern_it_should_not_throw()
{
// Arrange
string subject = "hello\r\nworld!";

// Act
Action act = () => subject.Should().MatchEquivalentOf("helloworld!");

// Assert
act.Should().NotThrow();
}

#endregion

#region Not Match Equivalent Of
Expand Down Expand Up @@ -496,6 +510,19 @@ public void When_a_string_does_match_the_equivalent_of_a_pattern_but_it_shouldnt
#endif
}

[Fact]
public void When_a_string_with_newlines_does_match_the_equivalent_of_a_pattern_but_it_shouldnt_it_should_throw()
{
// Arrange
string subject = "hello\r\nworld!";

// Act
Action act = () => subject.Should().NotMatchEquivalentOf("helloworld!");

// Assert
act.Should().Throw<XunitException>();
}

#endregion

#region Match Regex
Expand Down Expand Up @@ -585,6 +612,28 @@ public void When_a_string_is_matched_against_an_invalid_regex_it_should_throw_wi
#endif
}

[Fact]
public void When_a_string_is_matched_against_an_invalid_regex_it_should_only_have_one_failure_message()
{
// Arrange
string subject = "hello world!";
string invalidRegex = ".**"; // Use local variable for this invalid regex to avoid static R# analysis errors

// Act
Action act = () =>
{
using (new AssertionScope())
{
subject.Should().MatchRegex(invalidRegex);
}
};

// Assert
act.Should().Throw<XunitException>()
.Which.Message.Should().Contain("is not a valid regular expression")
.And.NotContain("does not match");
}

#endregion

#region Not Match Regex
Expand Down Expand Up @@ -672,6 +721,28 @@ public void When_a_string_is_negatively_matched_against_an_invalid_regex_it_shou
#endif
}

[Fact]
public void When_a_string_is_negatively_matched_against_an_invalid_regex_it_only_contain_one_failure_message()
{
// Arrange
string subject = "hello world!";
string invalidRegex = ".**"; // Use local variable for this invalid regex to avoid static R# analysis errors

// Act
Action act = () =>
{
using (new AssertionScope())
{
subject.Should().NotMatchRegex(invalidRegex);
}
};

// Assert
act.Should().Throw<XunitException>()
.Which.Message.Should().Contain("is not a valid regular expression")
.And.NotContain("matches");
}

#endregion

#region Start With
Expand Down
34 changes: 34 additions & 0 deletions Tests/Shared.Specs/TypeAssertionSpecs.cs
Expand Up @@ -1428,6 +1428,40 @@ public void When_asserting_a_selection_of_decorated_types_does_not_inherit_an_at
"*because we do*attribute was found*ClassWithInheritedAttribute*");
}

[Fact]
public void When_a_selection_of_types_do_inherit_unexpected_attribute_with_the_expected_properties_it_succeeds()
{
// Arrange
var types = new TypeSelector(typeof(ClassWithInheritedAttribute));

// Act
Action act = () => types.Should()
.NotBeDecoratedWithOrInherit<DummyClassAttribute>(a => ((a.Name == "Expected") && a.IsEnabled),
"because we {0}", "do");

// Assert
act.Should().Throw<XunitException>()
.WithMessage("Expected all types to not be decorated with or inherit *DummyClassAttribute*" +
" that matches ((a.Name == \"Expected\")*a.IsEnabled) because we do," +
" but a matching attribute was found on the following types:*" +
"*ClassWithInheritedAttribute*.");
}

[Fact]
public void When_a_selection_of_types_do_not_inherit_unexpected_attribute_with_the_expected_properties_it_succeeds()
{
// Arrange
var types = new TypeSelector(typeof(ClassWithoutAttribute));

// Act
Action act = () => types.Should()
.NotBeDecoratedWithOrInherit<DummyClassAttribute>(a => ((a.Name == "Expected") && a.IsEnabled),
"because we {0}", "do");

// Assert
act.Should().NotThrow();
}

[Fact]
public void When_injecting_a_null_predicate_into_TypeSelector_NotBeDecoratedWithOrInherit_it_should_throw()
{
Expand Down

0 comments on commit 503a453

Please sign in to comment.