DEV Community

Dariusz Rybicki for EL Passion

Posted on

Testing animations in UIKit

We take tests seriously at EL Passion. When implementing iOS apps, we always try to practice TDD, pair-programming and regular code-reviews. We want our software to be stable and bug-free. We often work on apps with outstanding design, that includes animations. In this case, we incorporate snapshot-based tests that work not only for static UI but also for animations.


Below you can see a real-life example, taken from E-commerce Today's deals interaction, iOS demo. We implemented custom animation for view controllers transition and tested it using snapshot tests.

Application Test snapshots
Ecommerce app Test snapshots


Take a look at a simplified example. Consider we have an animated button:

Button animation

It's implemented using native UIKit keyframes animation API:

func animate() {
        withDuration: 2,
        delay: 0,
        options: [],
        animations: {
                withRelativeStartTime: 0,
                relativeDuration: 0.5,
                animations: {
                    self.button.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
                    self.button.backgroundColor = .red
                withRelativeStartTime: 0.5,
                relativeDuration: 0.5,
                animations: {
                    self.button.transform = .identity
                    self.button.backgroundColor = .blue
Enter fullscreen mode Exit fullscreen mode

You can find full source code in ExampleViewController.swift file.


To test our animated button, we will use SnapshotTesting library from Point-Free.

In our XCTestCase we have to add the animated view to a window:

override func setUp() {
    sut = ExampleViewController()
    window = UIWindow(frame: CGRect(x: 0, y: 0, width: 220, height: 100))
    window.rootViewController = sut
    window.isHidden = false
Enter fullscreen mode Exit fullscreen mode

We can then control animation progress using UIViewPropertyAnimator. After setting the desired progress of the animation, we can make a snapshot of the containing window:

func testAnimation() {
    let animator = UIViewPropertyAnimator(duration: 1, curve: .linear, animations: {

    (0...10).map { CGFloat($0) / 10.0 }.forEach { animationProgress in
        animator.fractionComplete = animationProgress
            matching: window,
            as: .image(drawHierarchyInKeyWindow: true),
            named: "animation_\(String(format: "%02.0f", animationProgress * 10))"

    animator.finishAnimation(at: .current)
Enter fullscreen mode Exit fullscreen mode

This will result in generating 11 snapshot images that our animation will be compared to, every time we run tests:

Button animation snapshots

You can find full source code of presented XCTestCase subclass in ExampleViewControllerTests.swift file.


Copyright © 2019 EL Passion

Top comments (1)

sippi profile image

A Js implementation to test animations can be found here: