Red-Green-Code

Deliberate practice techniques for software developers

  • Home
  • About
  • Contact
  • Project 462
  • CP FAQ
  • Newsletter

Time Tortoise: Idle Time Unit Testing, Part 2

By Duncan Smith Aug 11 0

Idle

This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.

I’m in the process of resolving a unit test backlog for the Time Tortoise idle time feature. Last month, I explained why it’s acceptable in some situations to delay writing unit tests. I also covered a couple of unit testing best practices: interface-based design and minimizing the size of code-behind classes.

Over the past two weeks, I covered some challenges related to .NET assembly dependencies.

This week: more details on the idle time unit tests.

When User is Idle, Idle Timer Starts

The most basic idle time test scenario is this: when the user is idle, the idle timer starts. It sounds simple, but testing it requires a bit of unit test infrastructure.

Mock time

To unit test any scenario involving time, it’s important to avoid depending directly on System.DateTime, since you have no control over what the Now property of that type returns. That’s because it uses the system clock, so the test would have to depend on what the time happened to be when the test was running. This would make it difficult to test specific scenarios.

Instead, we want to depend on an IDateTime that can be mocked. For the current test, we’ll need an idle start time, idleStartTime and an idle end time, idleEndTime: the time range that the user is away from their computer. We can use Moq to ensure that methods return one of those times, as required by the test. In particular, we want Now to be idleEndTime, and we want the user’s last recorded activity to occur at idleStartTime.

Mock SignalR client

Because of the limitations of UWP, Time Tortoise can’t read the user’s idle time directly, so it receives it from Time Tortoise Companion (TTC) via SignalR. But in a unit test, we don’t want to rely on the assumption that TTC is running. So we need a mock TTC. Or more specifically, we need a mock SignalR client that pretends to be receiving messages from TTC.

As with the DateTime example, we can accomplish this by avoiding any direct dependencies on the SignalR client, and instead depending on an ISignalRClient interface. We can then use Moq to make it return the results we need.

The SignalR client exposes a queue of date/time messages that is updated whenever TTC detects activity from the user. So the last message in the queue stores the time of the user’s last recorded activity. If we make sure this time is idleStartTime, then the test preconditions will be satisfied.

The main page view model has a method called CheckIdleTime that is called on a timer in the application code. Since we don’t want timers in unit tests, we can just call it directly in the test. This method dequeues a message from the message queue and interprets it as the user’s last activity time. There are a number of things we can check to ensure that its interpretation is correct, but for this first test it suffices to check that the idle time segment start and end time are correct. If this is the case, we know that the idle time section of the user interface will also show the correct values.

Remaining Idle Time Tests

With this design in place, it’s relatively easy to write a few more tests and cover 100% of the idle time code. Here are the ones I came up with:

  • After the first idle check, ensure that the idle timer maintains correct start and end times in subsequent checks.
  • Ensure that if the user is not reported as idle, the idle timer doesn’t start.
  • When the user clicks the Include button, ensure that timing stops and that the most recent time segment ends at the idle end time (i.e., including the idle time period).
  • When the user clicks the Exclude button, ensure that timing stops and that the most recent time segment ends at the idle start time (i.e., excluding the idle time period).

(Image credit: Ted Major)

Categories: TT

Prev
Next

Stay in the Know

I'm trying out the latest learning techniques on software development concepts, and writing about what works best. Sound interesting? Subscribe to my free newsletter to keep up to date. Learn More
Unsubscribing is easy, and I'll keep your email address private.

Getting Started

Are you new here? Check out my review posts for a tour of the archives:

  • 2023 in Review: 50 LeetCode Tips
  • 2022 in Review: Content Bots
  • 2021 in Review: Thoughts on Solving Programming Puzzles
  • Lessons from the 2020 LeetCode Monthly Challenges
  • 2019 in Review
  • Competitive Programming Frequently Asked Questions: 2018 In Review
  • What I Learned Working On Time Tortoise in 2017
  • 2016 in Review
  • 2015 in Review
  • 2015 Summer Review

Archives

Recent Posts

  • Do Coding Bots Mean the End of Coding Interviews? December 31, 2024
  • Another Project for 2024 May 8, 2024
  • Dynamic Programming Wrap-Up May 1, 2024
  • LeetCode 91: Decode Ways April 24, 2024
  • LeetCode 70: Climbing Stairs April 17, 2024
  • LeetCode 221: Maximal Square April 10, 2024
  • Using Dynamic Programming for Maximum Product Subarray April 3, 2024
  • LeetCode 62: Unique Paths March 27, 2024
  • LeetCode 416: Partition Equal Subset Sum March 20, 2024
  • LeetCode 1143: Longest Common Subsequence March 13, 2024
Red-Green-Code
  • Home
  • About
  • Contact
  • Project 462
  • CP FAQ
  • Newsletter
Copyright © 2025 Duncan Smith