Transcripted Summary

In addition to regular assertions, NUnit provides some additional options for more advanced or unique conditions that may be helpful in your context.

# Warnings

Warnings in NUnit allow you to indicate in your test results that something might be affecting your test.

But unlike the assertions, they still allow your test to continue executing.

  • Maybe your backend services take a little time to process transactions or record data and because of that tests are failing intermittently.

  • Maybe you have a method that queries the status, but the timing still isn't perfect, and you don't want to stop and fail the whole test or put a hard sleep in your test either.

In this example, we combine using a warning with the After constraint.

After is a delay constraint which can be used with any other constraint to allow it to delay applying the constraint for a specified amount of time. It also gives the ability to poll at an interval to reduce the potential time a test is waiting.

We'll create a variable called “isProcessed” and set it to “false”; and this will pretend to be our method for checking the status.

To create a warning, we'll type Warn.Unless, and here we'll compare the “isProcessed” variable to our constraint. And our constraint is going to be Is.EqualTo(true) after one minute and poll every 10 seconds.

We'll add a console statement here so you can see that when we run the test the test isn't interrupted by our warning.

Now if we run the test, you can see the test is marked ignored.

But if we look at the test output, we can see that our console statement was executed.

There are 3 ways warnings can be used in your tests.

In addition to Warn.Unless, there's Warn.If, which will trigger the warning if the result evaluates to true. There's also Assert.Warn and this is a utility assertion which will always trigger a warning.

# Utility Assertions

In addition to Assert.Warn, NUnit provides 4 other utility assertions that let you specifically control the test status for reporting.

These are Assert.Pass, Assert.Fail, Assert.Ignore and Assert.Inconclusive.

**They each throw an exception, so wherever they are inside of your test, they will halt execution. **

And to prove this, we can write a test to confirm the exception by using the Exception constraint on the Throws class.

To see this, I'll enter Assert.That(Assert.Pass, Throws.Exception);.

And you can see the test passes.

A little suspicious. Is that test passing because it's doing what we expect or because of the Assert.Pass?

Most NUnit assertions throw an assertion exception, however, Assert.Pass throws a success exception.

We can confirm this using a more specific constraint.

Instead of Throws.Exception, we'll use Throws.TypeOf and specify the AssertionException type and run the test again.

And you can see that the test fails because Assert.Pass in fact throws the success exemption.

# Assumptions

Assumptions are a way to stay requirements for a test to be considered valid.

To use an assumption, you use Assume.That.

The method looks and feels the same as Assert.That. The difference is that when an assumption is not met, the test is halted but it hasn't failed — it's marked as inconclusive.

The reasoning behind this is that if your test is written, assuming a certain state and that state isn't present, well then it can't be accurately reported as passed or failed.

Perhaps your system is highly configurable and certain configuration settings might be required for the test to behave correctly.

You could add an assumption to your test so that future consumers of the test aren't surprised or confused by a test failure when a different environment or configuration is used.

This might also help make naming and organizing your tests a little easier.

Rather than have to encode that requirement into the test name or to filter it out of test runs or maybe explain it in a code comment, it becomes embedded in the test as a living part of the code base.

# Multiple Assertions

You may have heard of the one assertion per test rule.

It's a good rule, but that advice is most relevant to the context of unit testing where if you need multiple assertions, it might be an indicator that your unit test is doing too much.

What happens as you progress up the testing stack is you kind of need, or maybe really just want to verify multiple things — NUnit provides Assert.Multiple to help in these cases.

To use it, we'll create a test and name it, “WillThisMakeItThroughCodeReview”.

And inside the test, I'll write Assert.Multiple and then pass a Lambda function that contains a couple of assertion statements.

What happens is that rather than halt execution on the first failing assertion, NUnit stores any failures encountered and then reports all of them together.

Like it or not, it's better to have NUnit provide a means to accurately use multiple assertions in a test than the alternative.

NUnit didn't always have this feature. But what was really common was people would often get creative and invent ways to work around it. And what tended to happen is confusion and mistakes would creep into these work arounds resulting in tests that couldn't fail or difficult to maintain or report on.

# Alternative Assertion Libraries

There's no requirement to use the assertions provided by the NUnit framework.

There are open source alternatives like Fluent Assertions, Shouldly and others that have some really nice features like additional assertion types or a syntax you might prefer. Or even more detailed or readable test failure messages.

It really comes down to preference.

One nice thing about using a separate assertion library is they generally support multiple test frameworks, so your test code is slightly less coupled to the test framework.

The same applies to your assertion powers since your knowledge of that assertion library applies across all test frameworks as well.

And to see this, I've added a reference to Fluent Assertions via Nuget.

And I'll create a new test and call it “CheatingOnUnit”. Well, let's not go that far. Let's call it “AssertingWithFluentAssertions”.

Basically, all assertions in the Fluent Assertions library are extension methods that start with the method Should.

So, we'll take our “actual” value and use the .Should method and then .Be and then pass our “expected” value.

And when we run the test, you can see that NUnit discovered the test and reported the failure.

© 2024 Applitools. All rights reserved. Terms and Conditions Privacy Policy GDPR