Write unit tests which test the layout of a view in multiple configurations

Overview

Overview

This library enables you to write unit tests which test the layout of a view in multiple configurations. It tests the view with different data combinations and different view sizes. The library works in both Objective-C and Swift.

To learn how to use this library, there is a LinkedIn Learning course you can access completely for free authored by Kyle Sherman. You can access it here. It will teach you how to use LayoutTest and all of its features by video tutorial.

Motivation

When creating views, apps often have conditional logic which depends on the data used to setup the view. LayoutTest provides an easy way to define a data spec (a dictionary) which is then used to generate many different combinations of data. The library then uses this data to layout your view multiple times. For example, this is a small portion of the tests ran in our sample app:

In just one test, your view will be laid out multiple times with different data. You can then run test assertions on these views to verify that the layout and view content is correct. Also, the library will run a few tests automatically such as checking for Autolayout errors, missing accessibility, and overlapping views. Finally, the library makes it easy to test each view with different sizes so you can verify the view will work on different devices.

Docs

To get started, you should take a look at the docs:

https://linkedin.github.io/LayoutTest-iOS

Installation

Add to your unit test target:

pod 'LayoutTest'

or

pod 'LayoutTest/Swift'

Example

A simple test would look something like this. Check the docs for more detailed information and examples.

Objective-C:

@interface SampleTableViewCellLayoutTests : LYTLayoutTestCase
@end

@implementation SampleTableViewCellLayoutTests
- (void)testSampleTableViewCellLayout {
  [self runLayoutTestsWithViewProvider:[SampleTableViewCell class]
                            validation:^(UIView * view, NSDictionary * data, id context) {
    // Add your custom tests here.
  }];
}
@end

@implementation SampleTableViewCell (LayoutTesting)
  + (NSDictionary *)dataSpecForTest {
    return @{
      @"text": [[LYTStringValues alloc] init],
      @"showButton": [[LYTBoolValues alloc] init]
    }
  }
  + (UIView *)viewForData:(NSDictionary *)data
                reuseView:(nullable UIView *)reuseView
                     size:(nullable LYTViewSize *)size
                  context:(id _Nullable * _Nullable)context {
    SampleTableViewCell *view = (SampleTableViewCell *)reuseView ?: [SampleTableViewCell viewFromNib];
    [view setupWithJSON:data];
    return view;
  }
@end

Swift:

class SampleTableViewCellLayoutTests {
  func testSampleTableViewCell() {
    runLayoutTests() { (view: SampleTableViewCell, data: [NSObject: AnyObject], context: Any?) in
      // Add your custom tests here.
    }
  }
}

extension SampleTableViewCell: LYTViewProvider {
  class func dataSpecForTest() -> [NSObject: AnyObject] {
    return [
      "text": LYTStringValues(),
      "showButton": LYTBoolValues()
    ]
  }
  class func viewForData(data: [NSObject: AnyObject],
                    reuseView: UIView?,
                         size: LYTViewSize?,
                      context: AutoreleasingUnsafeMutablePointer<AnyObject?>) -> UIView {
    let cell = reuseView as? SampleTableViewCell ?? SampleTableViewCell.loadFromNib()
    cell.setupWithDictionary(data)
    return cell
  }
} 
Comments
  • Module 'LayoutTestBase' not found

    Module 'LayoutTestBase' not found

    I'm getting an error when trying to build for tests, even without #import "LayoutTest.h" anywhere.

    screen shot 2016-02-11 at 11 42 12 am

    It seems like the linker is having a hard time with the @import. I'm only linking these pods with my test target, which has a minimum build of iOS 7.0. I'm using cocoapods 0.38.2. I'm facing this issue in pod 'LayoutTest', '1.1.0' and pod 'LayoutTest', '~> 1.1.1'

    Is there anything I can do fix this issue? I would love to be able to integrate these view tests! It seems like a very well done testing framework. Thanks!

    opened by cconeil 24
  • false bool values not taken into account while laying out views

    false bool values not taken into account while laying out views

    LYTBoolValues() adds both true and false. But the views in the test are rendered for only true values. The test does not render any views for false values.

    opened by buppal 19
  • Missing SWIFT_VERSION in project file

    Missing SWIFT_VERSION in project file

    It appears that the project does not have the SWIFT_VERSION build setting set. When building with Xcode 8 I get:

    Use Legacy Swift Language Version (SWIFT_VERSION) is required to be configured correctly for targets which use Swift. Use the [Edit > Convert > To Current Swift Syntax menu to choose a Swift version or use the Build Settings editor to configure the build setting directly.
    
    opened by brennantaylor 13
  • Podfile unable to find a specification for `LayoutTest/Swift`

    Podfile unable to find a specification for `LayoutTest/Swift`

    I am trying to run the example found in GitHub, but I am running into a problem with my podfile.

    Anybody have a suggestion? The project is the exact one from GitHub and I can see LayoutTest/Swift in finder and in the project directory in xCode.

    ## Error from Command Line

    [!] The Podfile does not contain any dependencies. AMAC02NXBTSG3QC:LayoutTest-iOS-master randall.fong$ pod install Analyzing dependencies [!] Unable to find a specification for LayoutTest/Swift

    ## Podfile Definition

    target 'LayoutTest' do

    Uncomment this line if you're using Swift or would like to use dynamic frameworks

    use_frameworks!

    Pods for LayoutTest

    target 'LayoutTestTests' do inherit! :search_paths # Pods for testing pod 'LayoutTest' end

    end

    target 'LayoutTestBase' do

    Comment this line if you're not using Swift and don't want to use dynamic frameworks

    use_frameworks!

    Pods for LayoutTestBase

    pod 'LayoutTest/Swift'

    end

    directory xcodeproject
    opened by randyfong 11
  • Print path to html report on test failure

    Print path to html report on test failure

    It would be nice if the path was more easily accessible. If it were printed as part of the test I could click it in the console and open it directly which would be awesome!

    opened by brennantaylor 10
  • Issue 1 - Adding Snapshots support for failing tests

    Issue 1 - Adding Snapshots support for failing tests

    Snapshots will be saved for any failing test.

    • Snapshots are saved into the derived data folder for the current simulator.
    • Snapshots are saved in the folder structure LayoutTestImages/{CLASS-NAME}/{METHOD-NAME}/
    • Snapshots are saved in the format Width-{VIEW-WIDth}Height-{VIEW-HEIGHT}{HASH-OF-FAILING-DATA-DESCRIPTION}.png
    • Snapshots are logged to a index.html file for each class which includes the failure reason, image and data that was passed to the view.
    • The paths to the failing test index.html files are logged to the console at the end of the test bundle run.
    • Snapshots can be disabled using the LYTConfig
    • Snapshots can be limited per method using the LYTConfig
    opened by liamjdouglas 9
  • Allowing UIButton bckground image overlap.

    Allowing UIButton bckground image overlap.

    Find UIButton's private backgroundImageView and add it into self.viewsAllowingOverlap. Solving testing failure: Bottom right corner of <UIImageView: 0x7fb8c3d9dba0; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7fb8c3d9cd80>> overlaps upper left corner of <UIButtonLabel: 0x7fb8c61521c0; frame = (4.33333 11.3333; 35.6667 21.6667); text = 'Button'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fb8c61555a0>>. If this is intentional, you should add one of the views to viewsAllowingOverlap.

    opened by Biinngg 8
  • Carthage support

    Carthage support

    I've made minimal changes to make integration via Carthage possible.

    However, it might need further optimisations as I have not analysed lib structure in detail.

    opened by jakubvano 7
  • Should accessibility tests ignore subviews of `UIButton`?

    Should accessibility tests ignore subviews of `UIButton`?

    When a UIButton is under LayoutTest, the subviews trip the automatic accessibility checks.

    The ScreenReader seem to understand that the button is a button and doesn't recurse into the subviews.

    I also don't want to disable the accessibility tests for the button in question because I do want the test to fail I don't set a label on the button since I'm controlling it a little more precisely.

    So right now I'm resorting to the following in my tests:

    for subview in view.subviews {
        self.viewsAllowingAccessibilityErrors.addObject(subview)
    }
    

    I'm wondering if I'm missing something because this seems odd.

    opened by brennantaylor 6
  • Add in a max number of combinations flag to fail test cases if they get beyond a complexity threshold

    Add in a max number of combinations flag to fail test cases if they get beyond a complexity threshold

    With a large project and many folks writing layout tests, we want to have some control over the complexity of tests. One large test with 10s of combinations might be able to be broken down into a few tests, each with just a few combinations.

    Let me know what you think and if you have any feedback

    opened by danl3v 5
  • Issue 4 update layout with new data

    Issue 4 update layout with new data

    Added a test-case demonstrating that changing the text on a label from new test-data does not cause the label to be resized for the layout tests.

    Added a fix to force re-laying out for each piece of data.

    opened by KotiJocki 5
  • Can't call init with data

    Can't call init with data

    Hey! Really excited to get this project working for me.

    I have a number of views and view controllers I would like to test. I am using Realm in-memory to create Realm Objects to pass into my inits to instantiate my views and view controllers.

    failed: caught "NSInvalidArgumentException", "-[StoriesASDetailViewController initWithStory:]: unrecognized selector sent to instance 0x7fa5fbe07ce0"

    No matter what I try, be it a cell or tableviewcontroller, I just keep getting the error above.

    Any advice?

    ` +(UIView *)viewForData:(NSDictionary *)data reuseView:(UIView *)reuseView size:(LYTViewSize *)size context:(id _Nullable __autoreleasing *)context {

            StoryModel *story = [[StoryModel alloc] initWithDictionary:data error:nil];
    
            StoryRealm *local = [[StoryRealm alloc] initWithStoryModel:story];
    
            StoriesASDetailViewController *footer = [[StoriesASDetailViewController alloc] initWithStory:local];
    
            StoryDetailCell *cell = [footer.collectionNode cellForItemAtIndexPath:0];
    
            *context = footer;
    
            return cell;
    

    } `

    opened by mikegunning 4
  • Add more info to an autolayout failure (interceptsAutolayoutErrors)

    Add more info to an autolayout failure (interceptsAutolayoutErrors)

    Currently, the error only displays the message Failing test due to autolayout failure. Would be great to have a more detailed description to point to the view that is in error. Maybe getting a snapshot of the view would be helpful.

    opened by AngeloGLobo 0
  • Getting Test Failure due to UITableViewWrapperView overlapping UIImageView

    Getting Test Failure due to UITableViewWrapperView overlapping UIImageView

    I am getting the following test failure while layout testing my View Controller:

    failed - Bottom right corner of <UITableViewWrapperView: 0x7f8b9f1aca00; frame = (0 0; 375 559); gestureRecognizers = <NSArray: 0x608000251d90>; layer = <CALayer: 0x6080002311c0>; contentOffset: {0, 0}; contentSize: {375, 559}> overlaps upper left corner of <UIImageView: 0x7f8b9d75c260; frame = (3 553.5; 369 2.5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x608000230ee0>>. If this is intentional, you should add one of the views to viewsAllowingOverlap.

    However, my ViewController does not have any UIImageView elements. Do I need to add table view to viewClassesAllowingSubviewErrors?

    opened by SaketGupte 3
  • Layout tests fail on new 10.5-inch iPad

    Layout tests fail on new 10.5-inch iPad

    I have some layout tests for one of my collection view cells that is passing on every device except the new 10.5" iPad. Any ideas why it would be failing on that particular device? When I run my app on the 10.5" iPad, everything looks fine (and I get no layout errors). But in the layout test report, it looks like auto layout is broken.

    Anyone else having issues with the new iPad?

    I've included the test report below.

    LayoutTests.pdf

    opened by mpdifran 2
  • Would like to change the background color of the html report

    Would like to change the background color of the html report

    Alot of our views have white backgrounds. White on white is hard to see and twiddling the view in the test or the html page in chrome every time I want to see the edges isn't so fun.

    Could be nice to either easily change the background of the image being rendered into html or the css on the page or w/e from the test suite, or a dropdown on the page itself.

    Just throwing ideas out there.

    opened by brennantaylor 1
  • Specify allowOverlap between 2 specific views

    Specify allowOverlap between 2 specific views

    Right now you can only specify that you want a view to ignore any views overlapping it. However, it would be useful to say that you only allow an overlap of 2 specific views. This way you can catch any unwanted overlaps.

    opened by drumnkyle 2
Releases(6.0.1)
  • 6.0.1(Aug 27, 2019)

  • 6.0.0(Aug 27, 2019)

  • 5.03(Aug 22, 2019)

  • 5.02(Jul 11, 2019)

  • 5.0.1(Jul 11, 2019)

  • 4.0.2(Apr 17, 2018)

    Adds a new LYTDataValues subclass called LYTImageValues. This will generate instances of UIImage of a few different sizes so that you can easily test your UIImageViews.

    Source code(tar.gz)
    Source code(zip)
  • 4.0.1(Apr 17, 2018)

  • 4.0.0(Jan 11, 2018)

  • 3.0.2(Jan 3, 2018)

    Adds a new feature to lyt_before and lyt_after to accept a fromCenter arg. If set to YES, the before/after test will be relative to the center of a view instead of from the edge

    Source code(tar.gz)
    Source code(zip)
  • 3.0.1(Aug 3, 2017)

  • 3.0.0(Oct 11, 2016)

    Updating to Swift 3 This version updates the API in a very backwards incompatible way. It renames a bunch of methods using the new NS_SWIFT_NAME and NS_REFINED_FOR_SWIFT API. This means you can remove a bunch of the lyt_ prefixes in your code.

    Most of the changes should be pretty easy to see. Otherwise, see #31.

    If migrating is difficult, please submit an issue and we can create a migration guide.

    Source code(tar.gz)
    Source code(zip)
  • 3.0.0-beta4(Oct 11, 2016)

    Updating to Swift 3 This version updates the API in a very backwards incompatible way. It renames a bunch of methods using the new NS_SWIFT_NAME and NS_REFINED_FOR_SWIFT API. This means you can remove a bunch of the lyt_ prefixes in your code.

    Most of the changes should be pretty easy to see. Otherwise, see #31.

    If migrating is difficult, please submit an issue and we can create a migration guide.

    Source code(tar.gz)
    Source code(zip)
  • 3.0.0-beta3(Oct 11, 2016)

    Updating to Swift 3 This version updates the API in a very backwards incompatible way. It renames a bunch of methods using the new NS_SWIFT_NAME and NS_REFINED_FOR_SWIFT API. This means you can remove a bunch of the lyt_ prefixes in your code.

    Most of the changes should be pretty easy to see. Otherwise, see #31.

    If migrating is difficult, please submit an issue and we can create a migration guide.

    Source code(tar.gz)
    Source code(zip)
  • 3.0.0-beta2(Oct 11, 2016)

    Updating to Swift 3 This version updates the API in a very backwards incompatible way. It renames a bunch of methods using the new NS_SWIFT_NAME and NS_REFINED_FOR_SWIFT API. This means you can remove a bunch of the lyt_ prefixes in your code.

    Most of the changes should be pretty easy to see. Otherwise, see #31.

    If migrating is difficult, please submit an issue and we can create a migration guide.

    Source code(tar.gz)
    Source code(zip)
  • 3.0.0-beta1(Oct 10, 2016)

    Updating to Swift 3 This version updates the API in a very backwards incompatible way. It renames a bunch of methods using the new NS_SWIFT_NAME and NS_REFINED_FOR_SWIFT API. This means you can remove a bunch of the lyt_ prefixes in your code.

    Most of the changes should be pretty easy to see. Otherwise, see #31.

    If migrating is difficult, please submit an issue and we can create a migration guide.

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(Sep 23, 2016)

    Updating to Swift 3 This version mostly just updates the code to Swift 3 and doesn't change the API. We're going to update the API to a more Swift 3 friendly API in a future release.

    Source code(tar.gz)
    Source code(zip)
  • 1.4.0(Sep 22, 2016)

    • Upgrading project to Swift 2.3
    • Fixing a small bug in printing bool values in the HTML

    This release is mostly for Carthage users (to get the 2.3 Swift version). I won't do a release for Cocoapods since 1.3.0 works for them.

    Source code(tar.gz)
    Source code(zip)
  • 1.3.0(Aug 9, 2016)

    This release contains mostly bug fixes. Some of these bugs caused tests to pass which should have failed. Hence, updating to this version contains no backwards incompatible API fixes, but may cause your tests to fail.

    This is a good thing, because these tests should fail.

    Features:

    • LYT_FAILING_TEST_SNAPSHOT_DIR allows you to set the directory for failed test images
    • Travis integration! (yay CI)

    Fixes:

    • XML escaping
    • Doesn't test hidden views
    • Frame comparison bug fix
    • Swift 3 update
    • UIButton subviews are now ignored
    Source code(tar.gz)
    Source code(zip)
Mockit is a Tasty mocking framework for unit tests in Swift 5.0

Mockit Introduction Mockit is a Tasty mocking framework for unit tests in Swift 5.0. It's at an early stage of development, but its current features a

Syed Sabir Salman-Al-Musawi 118 Oct 17, 2022
Trying to implement Unit Tests for @Binding properties in a ViewModel

BindingTester Trying to implement Unit Tests for @Binding properties in a ViewModel ViewModel to be tested class SheetViewModel: ObservableObject {

Raphael Guye 0 Oct 22, 2021
Library for unifying the approach to network mocking in iOS unit- & UI-tests.

TinkoffMockStrapping Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installati

Online financial ecosystem 22 Jan 3, 2023
Catching fatal errors in unit tests

Precondition Catching When running tests which hit fatal errors, often preconditions the built-in support with XCTest. One package which supports cach

Brennan Stehling 0 Nov 28, 2021
TestSchedulerDemo - Demonstration code for iOS Unit Tests and Asynchronous

TestSchedulerDemo This repository contains demonstration code for my Medium arti

Carsten Wenderdel 0 Mar 19, 2022
Marvel - Marvel Characters App using MVVM, and including unit tests

Marvel About The purpose of this project is to develop a app using MVVM, and inc

null 1 Mar 20, 2022
Detailed explanations and implementations of various maths concepts for writing high performance code/algorithms backed with Unit tests.

Detailed explanations and implementations of various maths concepts which can help software Engineers write high performance code/algorithms backed with Unit tests.

Mussa Charles 2 Sep 25, 2022
Bluepill is a reliable iOS testing tool that runs UI tests using multiple simulators on a single machine

Bluepill is a tool to run iOS tests in parallel using multiple simulators. Motivation LinkedIn created Bluepill to run its large iOS test suite in a r

Mobile Native Foundation 3.1k Jan 3, 2023
The XCTest Project, A Swift core library for providing unit test support

XCTest The XCTest library is designed to provide a common framework for writing unit tests in Swift, for Swift packages and applications. This version

Apple 1k Jan 4, 2023
XCTestExtensions is a Swift extension that provides convenient assertions for writing Unit Test.

XCTestExtensions Features XCTAssertEventually (that convenient assertions for writing Unit Test). Use "XCTAssertEventually", you can write asynchronou

shindyu 22 Dec 1, 2022
I built this application with unit testing and test-driven development to understand TDD theory and practice

TestDrivenDevelopment Description I built this application with unit testing and test-driven development to understand TDD theory and practice, to wri

null 1 Dec 21, 2021
A collection of useful test helpers designed to ease the burden of writing tests for iOS applications.

MetovaTestKit is a collection of useful test helpers designed to ease the burden of writing tests for iOS applications. Requirements Installation Usag

null 23 Aug 29, 2021
Test-To-Do-List - Test To Do List with core data

test-To-Do-List This is my first pet project with core data Launch screen Main s

Artem 0 Feb 26, 2022
Kfm-ios-test - Test online for iOS Developer position in Kimia Farma or PT. Buana Varia Komputama

kfm-ios-test Kimia Farma Mobile iOS Test Test online for iOS Developer position

Erwindo Sianipar 3 Feb 23, 2022
A Mac and iOS Playgrounds Unit Testing library based on Nimble.

Spry Spry is a Swift Playgrounds Unit Testing library based on Nimble. The best thing about Spry is that the API matches Nimble perfectly. Which means

Quick 327 Jul 24, 2022
Runtime introspection and unit testing of SwiftUI views

ViewInspector ??️‍♂️ for SwiftUI ViewInspector is a library for unit testing SwiftUI views. It allows for traversing a view hierarchy at runtime provi

Alexey Naumov 1.5k Jan 8, 2023
Erik is an headless browser based on WebKit. An headless browser allow to run functional tests, to access and manipulate webpages using javascript.

Erik Erik is a headless browser based on WebKit and HTML parser Kanna. An headless browser allow to run functional tests, to access and manipulate web

Eric Marchand 544 Dec 30, 2022
Swift Package with examples of how to tests iOS apps

GimmeTheCodeTDD A swift package with examples of unit tests in iOS development. Requirements Xcode 13 Content Dependency Injection Constructor Injecti

Dominik Hauser 8 Oct 11, 2021
Small library to easily run your tests directly within a Playground

[] (https://developer.apple.com/swift/) Build Status Branch Status master develop About PlaygroundTDD enables you to use TDD directly on Xcode Playgro

Whiskerz AB 317 Nov 22, 2022