DateKit gives you a handy way to provide the current date to your iOS app, while simultaneously making it quick and easy to mock dates in your tests.
In production code, you simply call DateKit.now() to get the current date, instead of using Date() or NSDate().
Then, in test code, you can mock the current date by calling DateKit.mockCurrentDate(as:), and passing in a string of the format "yyyy-MM-dd HH:mm:ss". At this point, DateKit.now() will return the mocked date/time instead of the actual date/time.
DateKit also provides a helper method — getDate(as:) — for creating standalone dates. This is a simple wrapper to make it easier and more succinct to create a new date object.
DateKitUI extends the functionality of DateKit by giving you full control of mocked dates in your Xcode UI tests. Since you can't access the inner workings of your app during UI testing in the same way that you would during a unit test, DateKitUI employs a nearly-hidden UITextField element to allow you to enter date-strings via the UI instead.
Drag the DateKit directory into your Xcode project.
In your production code, use DateKit.now() anywhere you would normally use Date() or NSDate(), such as in this contrived code sample:
account.activationDate = DateKit.now()
Now, in your unit tests, you can control what DateKit.now() returns by using DateKit.mockCurrentDate(as:)—which means you can effectively move your tests forward in time to make sure that time/date-critical code works the way you intended.
func testUserMembershipYears_givenOneYear_returnsCorrectCount() {
DateKit.mockCurrentDate(as: "2017/11/17 23:59:59")
let testUser = AccountManager.initializeNewAccount()
DateKit.mockCurrentDate(as: "2018/11/28 03:21:18")
let actual = testUser.membershipYears
let expected = 1
XCTAssertEqual(expected, actual)
}
Should you need, you can mock other dates as well, using DateKit.getDate(as:)—like I do here to test that my numDaysElapsed(from:to:) method is functioning correctly.
func testNumDaysElapsed_givenSameDate_returnsZero() {
var begin = DateKit.getDate(as: "2018-08-09 00:30:30")
var end = DateKit.getDate(as: "2018-08-09 05:22:18")
var expected = 0
var actual = numDaysElapsed(from: begin, to: end)
XCTAssertEqual(expected, actual)
}
Using DateKitUI in your UI tests is fairly straightforward—first, choose a UIViewController where you'll instantiate and interact with the hidden UITextField.
override func viewDidLoad() {
super.viewDidLoad()
DateKit.enableUITests(view: view)
}
Now, in XCTestCase, you can setup your UI tests like this:
override func setUp() {
super.setUp()
app.launch()
date = app.textFields["DateKitUI"]
}
Changing the date in your UI tests looks like this:
date.set("1995/1/1 00:00:00")
And if you like, you can use this handy extension to set the date, close the app, then relaunch it—all in one step:
app.launchTo("2000/1/3 01:02:00")
That's it! I hope you find DateKit as useful as I have. Now get out there and test, test, test!
- Email: [email protected]
- GitHub: cmilr
Distributed under the MIT license. See LICENSE
for more information.