Git Product home page Git Product logo

layouttest-ios's Introduction

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
  }
} 

layouttest-ios's People

Contributors

biinngg avatar cezarywojcik avatar chenxiao0228 avatar crleona avatar danl3v avatar dark2torch avatar drumnkyle avatar duglsyoung avatar indrashan avatar jakubvano avatar jmkk avatar kotijocki avatar liamjdouglas avatar liguopku avatar maniramezan avatar mpdifran avatar oliverhu avatar plivesey avatar terrychen1122 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

layouttest-ios's Issues

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!

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.

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!

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

Bitcode issue

I am trying to integrate LayoutTest library 1.2.1 into a project that does not yet suppot BitCode, through cocoa pods that generats dynamic frameworks. However, Xcode gives me following error

does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64.
After disabling the bitcode in Pod project, it beings to work. I wonder why other libraries who have BitCode enabled work fine but LayoutTest doesn't.

I ended up disabling BitCode for all Pods using the link below.
http://stackoverflow.com/questions/32640149/disable-bitcode-for-project-and-cocoapods-dependencies-with-xcode7

How to use it with UIViewController?

(UIView *)viewForData:(NSDictionary *)data reuseView:(nullable UIView *)reuseView size:(nullable LYTViewSize *)size context:(id _Nullable * _Nullable)context; this function takes an object of UIView so how to use object of UIViewController? as I have all my IBOutlets connnected to UIViewController.

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;

}
`

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.

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

Layout is not updated with new input data

  • Construct a view with two labels where one label will overlap another when a long string is used.
  • Run a test case that provides a very long string as the only input for one of the labels and observe this test failing as expected.
  • Run another test case that provides LYTStringValues() and observe that the expected failing test passes.

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.

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?

Readme

Hey there! Really interesting project! I'm a bit confused about the motivation of the tool; like, what problem does this solve, and how is it better than other solutions? I'd love to see an explanation in the readme, maybe like a before-and-after using this library.

Thanks again! Really cool!

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.