We have a test suite at work which tests a retry decorator class works as expected. One of the tests checks that when the inner implementation throws an exception, it will log the number of times it has failed:
[Test]
public async Task ShouldLogRetries()
{
    var mockClient = Substitute.For<IContractProvider>();
    var logger = Subsitute.For<ILogger>();
    var sut = new RetryDecorator(mockClient, logger, maxRetries: 3);
    mockClient
        .GetContractPdf(Arg.Any<string>())
        .Throws(new ContractDownloadException());
    try
    {
        await sut.GetContractPdf("foo");
    }
    catch (Exception e){}
    logger.Received(1).Information(Arg.Any<string>(), 1);
    logger.Received(1).Information(Arg.Any<string>(), 2);
    logger.Received(1).Information(Arg.Any<string>(), 3);
}
But looking at this test, I couldn’t easily work out what the behaviour of sut.GetContractPdf("foo") was supposed to be; should it throw an exception, or should it not? That fact that there is a try...catch indicates that it might throw an exception, but doesn’t give any indication that it’s required or not.
try
{
    await sut.GetContractPdf("foo");
}
catch (Exception e)
{
}
Since we have the Shouldly library in use, I changed the test to be a little more descriptive:
Should.Throw<ContractDownloadException>(() =>
    sut.GetContractPdfForAccount("foo")
);
Now we know that when the decorator exceeds the number of retries, it should throw the inner implementation’s exception.
This in itself is better, but it also raises another question: Is the test name correct? Or should this now be two separate tests? One called ShouldLogRetries, and one called ShouldThrowInnerExceptionOnRetriesExceeded?
Even though I ended up adding the second test, I still left the first test with the Should.Throw(...) block, as it is still more descriptive at a glance than the try...catch.