Skip to main content

.NET 8–It’s time to get rid of these flaky tests!

There is only one thing worse than having no tests and that is having flaky tests. You know, tests that sometimes fail and sometimes succeed when the code itself didn't change. One of the biggest reasons this can happen is when your tests have time related logic.

My tests succeed on Monday but not during the weekend.

Sidenote: there is a cool Azure DevOps feature specifically to handle and fix flaky tests. Anyway that is not the topic of this post.

In .NET 8 Microsoft tried to fix this by introducing a new time abstraction API. Instead of directly calling DateTime.Now or DateTime.UtcNow inside your code, you can now use the TimeProvider class and ITimer interface. Together they offer time abstraction functionality, facilitating the simulation of time in testing scenarios.

public abstract class TimeProvider
{
public static TimeProvider System { get; }
protected TimeProvider()
public virtual DateTimeOffset GetUtcNow()
public DateTimeOffset GetLocalNow()
public virtual TimeZoneInfo LocalTimeZone { get; }
public virtual long TimestampFrequency { get; }
public virtual long GetTimestamp()
public TimeSpan GetElapsedTime(long startingTimestamp)
public TimeSpan GetElapsedTime(long startingTimestamp, long endingTimestamp)
public virtual ITimer CreateTimer(TimerCallback callback, object? state,TimeSpan dueTime, TimeSpan period)
}
public interface ITimer : IDisposable, IAsyncDisposable
{
bool Change(TimeSpan dueTime, TimeSpan period);
}
view raw TimeProvider.cs hosted with ❤ by GitHub

Remark: Microsoft was so nice to backport these APIs and made them available in a separate NuGet package Microsoft.Bcl.TimeProvider.

So now we can update our code to use the TimeProvider class instead:

public class Calendar
{
private readonly TimeProvider _timeProvider;
public Calendar(TimeProvider timeProvider)
{
_timeProvider = timeProvider;
}
public bool IsItWeekend()
{
return _timeProvider.GetLocalNow().DayOfWeek == DayOfWeek.Saturday || DayOfWeek.Sunday;
}
}
view raw Calendar.cs hosted with ❤ by GitHub

If we now want to test our code we can use the Microsoft.Extensions.TimeProvider.Testing package. This includes a TimeProvider implementation called FakeTimeProvider which gives us explicit control over the flow of time.

An example:

[Fact]
public void IsItWeekend()
{
// Arrange
var fakeTimeProvider = new FakeTimeProvider();
// Set the current UTC time
fakeTimeProvider.SetUtcNow(new DateTime(2024, 2, 7));
fakeTimeProvider.SetLocalTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Greenwich Standard Time"));
// Act
var result = new Calendar(fakeTimeProvider);
//Assert
Assert.False(result.IsItWeekend());
}
view raw WeekendTest.cs hosted with ❤ by GitHub

These new abstractions can also be used in asynchronous program execution thanks to some new overloads:

public partial class Task : IAsyncResult, IDisposable
{
public static Task Delay(TimeSpan delay, TimeProvider timeProvider)
}
public partial class Task<TResult> : Task
{
public new Task<TResult> WaitAsync(TimeSpan timeout, TimeProvider timeProvider)
}
view raw Task.cs hosted with ❤ by GitHub

Nice!

Popular posts from this blog

Kubernetes–Limit your environmental impact

Reducing the carbon footprint and CO2 emission of our (cloud) workloads, is a responsibility of all of us. If you are running a Kubernetes cluster, have a look at Kube-Green . kube-green is a simple Kubernetes operator that automatically shuts down (some of) your pods when you don't need them. A single pod produces about 11 Kg CO2eq per year( here the calculation). Reason enough to give it a try! Installing kube-green in your cluster The easiest way to install the operator in your cluster is through kubectl. We first need to install a cert-manager: kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.yaml Remark: Wait a minute before you continue as it can take some time before the cert-manager is up & running inside your cluster. Now we can install the kube-green operator: kubectl apply -f https://github.com/kube-green/kube-green/releases/latest/download/kube-green.yaml Now in the namespace where we want t...

Azure DevOps/ GitHub emoji

I’m really bad at remembering emoji’s. So here is cheat sheet with all emoji’s that can be used in tools that support the github emoji markdown markup: All credits go to rcaviers who created this list.

DevToys–A swiss army knife for developers

As a developer there are a lot of small tasks you need to do as part of your coding, debugging and testing activities.  DevToys is an offline windows app that tries to help you with these tasks. Instead of using different websites you get a fully offline experience offering help for a large list of tasks. Many tools are available. Here is the current list: Converters JSON <> YAML Timestamp Number Base Cron Parser Encoders / Decoders HTML URL Base64 Text & Image GZip JWT Decoder Formatters JSON SQL XML Generators Hash (MD5, SHA1, SHA256, SHA512) UUID 1 and 4 Lorem Ipsum Checksum Text Escape / Unescape Inspector & Case Converter Regex Tester Text Comparer XML Validator Markdown Preview Graphic Col...