Giter Club home page Giter Club logo

succinct's Introduction

Succinct (サシンクト)

Build Status Swift Package Manager Compatible Carthage Compatible Cocoapods Compatible GitHub tag codecov jazzy docs GitHub license

Use Succinct to unit test the behaviors of your iOS UI in a way that is de-coupled from the private implementation details of your views.

  • ⚡️ SPEED: Get lightning fast feedback through unit tests instead of waiting around for your UI tests to give you an accurate result... sometimes.
  • 🔍 ENCAPSULATION: By searching through the view hierarchy, the internals of your UI can be kept private, honoring encapsulation.
  • 🛠 ARCHITECTURE AGNOSTIC: Any architectural pattern (MVC, MVP, MVVM, etc) can be used to implement your UI.
  • 🧩 FREEDOM TO REFACTOR: Refactor to a different architectural pattern without having to change your tests.

IMPORTANT:_ Succinct is a work in progress and does not support every single aspect of testing iOS view hierarchies just yet. Functionality in as it is needed. If there's something you'd like to see included please feel free to open an issue or make a PR. 👍🏻

Installation

Swift Package Manager (SPM)

In Xcode, select the File -> Add Packages... menu option and enter https://github.com/derekleerock/Succinct for the the repository URL. Select the desired Dependency Rule and Target then click "Add Package".

Carthage

Simply include Succinct in your Cartfile.private:

github "derekleerock/Succinct"

And include it in your test target.

Cocoapods

Simply add Succinct to your Podfile's test target:

target 'MyAmazingApp' do
  ...
  
  target 'MyAmazingAppTests' do
    inherit! :search_paths

    pod 'Succinct'
  end
end

Documentation

📄 Documentation via GitHubPages

Automatic documentation generated thanks to Jazzy, GitHubPages and Travis-CI integration and some great guidance from @jgsamudio in this blog post.

Making a Contribution

Development for Succinct is done right here through GitHub Issues so anyone can contribute and understand the current state of the framework. If there is functionality that you're looking for that is not included, please feel free to open an issue or make a PR with your suggested feature and tests so we can discuss.

Setting up for development

Succinct uses the Swift Package Manager integration in Xcode to install dependencies. Xcode will fetch these the first time you build and run the tests.

Running the tests

All of Succinct's tests have been TDD'd using Quick and Nimble - meaning that you can use Succinct with confidence that it will give you accurate results for the functionality that it provides.

There are two different test suites for Succinct: Unit Tests and Simulator Tests.

Unit Tests

These unit tests do not require a host application to run, which means that they can run without the simulator. This makes them lightning fast!

They can be executed using:

$ make tests

Simulator Tests

These unit tests require the simulator since they are interacting with elements in the UI. They are still fast because they are unit tests, but launching the simulator takes a little bit of time.

They can be executed using: $ make simulator-tests

All Tests

Both test suites can be executed using:

$ make alltests

Before completing your PR please be sure your functionality is properly tested and you've confirmed that all tests run successfully - thank you! 🙇🏻‍♂️

License

Succinct is licensed under the MIT License. Please see the LICENSE file.

succinct's People

Contributors

dependabot[bot] avatar immenor avatar rgravina avatar theextremeprogrammer avatar wrightak 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

Watchers

 avatar  avatar  avatar  avatar

succinct's Issues

Add support for UISearchController

UISearchController contains some elements which might need to be searched such as:

  • searchResultsController (UIViewController)
  • searchBar

Only check for views visible to the user

The idea is to make it so that when searching for any type of UIKit component, it only can find ones that are visible to the user. If we were to go by apple's definition of if a view can't be touched, that would be isHidden == true or alpha < 0.01.

For example, if I have a label that is currently hidden, findLabel(withExactText:) should no longer be able to find that label.

Improve test readability of attributed string tests

Manually specifying a range of a string using magic numbers in the test / builder for attributed strings can both be difficult to understand what it's pointing to and easy to make a mistake when adding/modifying a test.

For those tests where a given sequence of characters exists only one time, might it be better to specify the actual string that you want the attributes to be applied to? I think this might help the tests become a bit more readable.

Here's an example of one test that I've modified to allow this to be done by adding a new method to the builder:

https://github.com/derekleerock/Succinct/blob/b93b9cedbb1139ad8b22feb5453261c3d0fd60a4/SuccinctTests/NSAttributedString/NSAttributedString%2BAttributesSpec.swift#L13

If you think this would be a good improvement, can you make this same update to the remaining tests that could benefit from this? (The last test where you have the same string in there twice probably can't use this approach but I think most of the others can.)

Thanks!

Searching for labels should exclude searching UISegmentedControls

For example: findLabel(withExactText: "Issues") returns true if there is a UISegmentedControl with a title of "Issues".

UISegmentedControls should be excluded when searching for UILabel to ensure that searching for UILabels is exclusive to UILabel. If the developer wants to search for a UISegmentedControl, then the developer should call those methods explicitly.

Research ways to assist with automating documentation

It would be helpful to have some documentation which covers all of the available APIs - however this is a lot of work (and duplication potentially) given the number of functions that are supported / could be supported.

This issue is to research ways in which documentation could potentially be automated to make the process of updating and maintaining the documentation easier.

Are there other solutions that other frameworks make use of? What is the most efficient way to generate this information automatically and minimize the manual nature of preparing / maintaining documentation?

Re-add support for "tapLeftBarButtonItem()" back into the framework

This was removed in commit 9eeff1f due to assuming that it was no longer needed assuming that tapBarButtonItem(systemItem:) satisfied this need.

tapBarButtonItem(systemItem:) can only be used with system items whereas tapLeftBarButtonItem() can be used with any kind of UIBarButtonItem, therefore tapLeftBarButtonItem() support is still helpful.

Searching for attributed text crashes when the text does not exist

There's a forced unwrapped optional when looking for the search string in an attributed string:

https://github.com/derekleerock/Succinct/blob/413cda993cbbe6011feec8cdb7a6edf1939a9436/Succinct/NSAttributedString/NSAttributedString%2Battributes.swift#L13

Therefore when a search string that doesn't exist in the attributed string is searched for, the function crashes.

Here's a test that re-creates this issue:

context("when the search string does not exist in the attributed string") {
    it("cannot find the string") {
        let redForegroundColor = [NSAttributedString.Key.foregroundColor : UIColor.red]
        let mutableAttributedString = NSMutableAttributedStringBuilder(withText: "Foreground and Background")
            .withAttributes(
                redForegroundColor,
                range: NSRange(location: 0, length: 10)
            )
            .build()


        let attributedString = mutableAttributedString.copy() as! NSAttributedString
        expect(attributedString.containsExactString("Invalid", withAttributes: redForegroundColor)).to(beTrue())
    }
}

Can you add this test and adjust the code to make it pass? Thanks!

Add support for using accessibility identifiers:

Consider adding support for accessibility identifiers. For example:

  • findView(withAccessibilityIdentifier:)
  • findButton(withAccessibilityIdentifier:)
  • findLabel(withAccessibilityIdentifier:)
  • findTextField(withAccessibilityIdentifier:)

Add support for Cocoapods

Cocoapods Specs and the Specs Repo: https://guides.cocoapods.org/making/specs-and-specs-repo.html
Podspec Syntax Reference: https://guides.cocoapods.org/syntax/podspec.html

  • Create Succinct.podspec locally using $ pod spec create https://github.com/derekleerock/Succinct

  • Configure pod and confirm using $ pod spec lint Succinct.podspec --verbose

  • Test local podspec with Xcode project pointing to local Succinct with podspec

  • Test GitHub podspec with Xcode project pointing to Succinct Git repo

  • Submit pod to the trunk using $ pod trunk push Succinct.podspec (Reference) Link: https://cocoapods.org/pods/Succinct

  • $ pod trunk register [email protected] 'Name' --description='Computer name/session'

  • $ pod trunk push Succinct.podspec --allow-warnings

  • Tag latest version of Succinct for a release which resolves the latest Xcode warnings

  • Push the new tagged version to Cocoapods

  • Update local Cocoapods repository and re-test locally using $ pod repo update

  • Update README.md with information on installation and Cocoapods support

Backfill tests for existing functionality

Most of Succinct's functionality was built using TDD - however some portions were built using TDD within the context of an actual iOS app implementation. These functions were not test-driven inside the framework, but inside the iOS app.

This milestone is for backfilling tests for these functions to ensure that they continue to work as expected within the context of the framework.

(Tests for some of these may have been added but this is the last list that I had created.)

  • UICollectionView+Testing
  • UIView+UIView
  • UIViewController+UIView
  • UIView+UITextField
  • UIViewController+UISegmentedControl
  • UIView+UISegmentedControl
  • UIView+UILabel
  • UIView+UIStepper
  • UIViewController+UIStepper
  • UIViewController+UITextField
  • UIView+UIPickerView
  • UIView+UIImage
  • UIViewController+UIImage
  • UIView+UISwitch
  • UIViewController+UIPickerView
  • UIPickerView+SelectComponent

Adjust NSMutableAttributedStringBuilder to return NSAttributedString

Looks like every time an attributed string is created using the builder it's converted from a mutable attributed string to an attributed string in each test:

https://github.com/derekleerock/Succinct/blob/b93b9cedbb1139ad8b22feb5453261c3d0fd60a4/SuccinctTests/NSAttributedString/NSAttributedString%2BAttributesSpec.swift#L17

If this is the case, maybe it'd be easier to adjust the builder to just return an attributed string and remove this line from the tests?

For example, with a builder list this:

struct NSAttributedStringBuilder {
    private var attributedString: NSMutableAttributedString

    init(withText text: String) {
        attributedString = NSMutableAttributedString(string: text)
    }

    ...

    func build() -> NSAttributedString {
        return attributedString.copy() as! NSAttributedString
    }
}

The test can be cleaned up like this:

it("can find text with a foregroundColor") {
    let redForegroundColor = [NSAttributedString.Key.foregroundColor : UIColor.red]
    let attributedString = NSMutableAttributedStringBuilder(withText: "Foreground and Background")
        .withAttributes(redForegroundColor, forString: "Foreground")
        .build()


    expect(attributedString.containsExactString("Foreground", withAttributes: redForegroundColor)).to(beTrue())
}

What do you think?

I'm not a huge fan of the force-cast to an NSAttributedString but it doesn't look like there's a nicer way to create attributed strings... =T

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.