Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Chore] Add KIF and KIF Target #95

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open

[Chore] Add KIF and KIF Target #95

wants to merge 2 commits into from

Conversation

blyscuit
Copy link
Collaborator

@blyscuit blyscuit commented Jan 11, 2023

What happened 👀

  • Add KIF UITest.
  • Add KIF target to schemes and fastlane.
  • Part of iOS chapter KIF adoption.

Insight 📝

  • Add new target CryptoPricesKIFUITests.
  • Add package KIF, Quick, Nimble to project for target CryptoPricesKIFUITests.
  • Add test coverage to Staging scheme.

Proof Of Work 📹

Before KIF:

Screen Shot 2023-01-10 at 18 38 47

After KIF:

Screen Shot 2023-01-10 at 18 38 50

@blyscuit blyscuit self-assigned this Jan 11, 2023
@blyscuit blyscuit added this to the 0.7.0 milestone Jan 11, 2023
@blyscuit blyscuit marked this pull request as ready for review January 11, 2023 02:34
import Nimble
import Quick

final class HomeSpec: QuickSpec {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we are putting this KIF test in the main project, but since we are using a modular architecture, this UI test should be placed directly in the Home package instead. What do you guys think? @Thieurom @nkhanh44

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Firstly, welcome to CryptoPrices @blyscuit 🎉

@minhnimble Yes, that's exactly what I was going to say 😄

For our architecture, the tests of a module will be placed in the corresponding package. So basically we would have two new test targets for the Home and MyCoin respectively.

The CryptoPricesKIFUITests target you created is still useful if we want to make some kind of integration test, like tapping a row on the TrendingCoins section on the Home will navigate to the MyCoin with correct UIs, ...

I think today I'm gonna take a look at KIF to check how to best integrate it into our project 🙏

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A warm welcome to @blyscuit 🕺 .
@minhnimble @Thieurom I agree 💪 . I used to use KIF before but in our architecture, it's something I need to research a little bit :D. I will take a look at this after my tasks are done 🙏 .

Copy link
Collaborator Author

@blyscuit blyscuit Jan 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

KIF is "an iOS integration test framework", it requires some sort of 'app' to run the test. Underneath it works similarly to XCUITest (meant as a replacement of XCUITest): Find view in app > interact with app via accessibility components.

I think this discussion is referring to Unit test of the views, which can be done through ViewInspector that David presented or with Snapshot Testing that Thieu briefly discussed.

The reason that KIF runs on a unit test scheme is because it uses application code to execute the test ie: UIScreen.main.currentViewController to find a specific view and interact with it. I believe this can cause some confusion to first time adopter.

Alternatively the UI modules need to have app that show the UI on the simulator (extra main class that is used for testing only), which is also a unit test idea and fits better with ViewInspector.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I'm pushing KIF to the chapter and this project is because iOS dev are less likely to want to add integration test because how fragile XCUITest is. But with KIF we can be confident about our integration test and is way easier to work with.

Copy link
Collaborator Author

@blyscuit blyscuit Jan 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the modular architecture note, I think it will make sense to add KIF to the module if the module act as a user's story ie: register, kyc, feature1, feature2, then it would make sense to create a demo-main class for testing. Currently this modular architecture is separating the feature module to smaller UI modules.

Copy link
Collaborator

@Thieurom Thieurom Jan 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your insights @blyscuit 🙏

KIF is "an iOS integration test framework", it requires some sort of 'app' to run the test.

That's what I thought in the first place

The CryptoPricesKIFUITests target you created is still useful if we want to make some kind of integration test, like tapping a row on the TrendingCoins section on the Home will navigate to the MyCoin with correct UIs, ...

So basically, with the same KIF framework (without an additional one like ViewInspector) we can achieve 2 purposes:

  • Add the Unit test of the views for each module. It needs some extra work like wrapping in a UIHostingController (it can be extracted to a helper/extension though) among other things. I think we don't have time for this now!
  • Add the integration tests, which need to be implemented on the app level as you did here. From what I've seen, it's quite similar to another tool like Appium (I remembered my QA guys and gals wrote a lot of test scripts and scenarios in my former companies with this 😄). We should keep going with this! Still, I need some time to play around with KIF before making some useful feedback 🙏

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your two points here are correct.

It needs some extra work like wrapping in a UIHostingController

With the current structure of the modules (Home and MyCoin), the UIHostingController would also be implemented in a new Target (same or new project file) because the Swift module has limitation of creating an app target inside the module.

it's quite similar to another tool like Appium

Same as Appium, but much faster build & run and written in Obj-c/Swift.

@Thieurom
Copy link
Collaborator

Thieurom commented Jan 16, 2023

Hi @blyscuit

I checked out this branch and played around with it a little bit. There're some concerns I'd like to share here; kindly clarify 🙏 I might miss something since I didn't have too much time with KIF.

  • We kind of agree that the test for individual feature view should be placed in the corresponding package; the CryptoPricesKIFUITests target was meant for the integration test. So the newly-added test class (and its filename) should be AppSpec, and it would start with something like this:

    @testable import Home
    @testable import MyCoin
    import Nimble
    import Quick
    
    final class AppSpec: QuickSpec {
    
      override func spec() {
        //
      }
    }
  • When I ran the test for HomeSpec locally, the test passed, but the logs showed many Main Thread Checker issues. It seems to do with the KIF's internal implementation (how it launches and runs the app.

    Screenshot 2023-01-16 at 09 59 43 Also, the logs show the app called the API. I think we might need some setup to inject the mocked dependencies for the app before executing any tests 🙏
  • When I ran the test locally but with a different expected result (I'd like to see how KIF fails the test):

    self.tester().waitForView(
      withAccessibilityLabel: "Lorem Ipsum"
    )

    It ran pretty slowly and logged hundreds of [Assert] Unsupported enumeration of UIWindowScene windows on non-main thread. then crashed:

    Screen.Recording.2023-01-16.at.10.28.46.mov
  • The test ran on the CI (GitHub Action) slowly and failed; strangely, it didn't fail the workflow 🤔
    Screenshot 2023-01-16 at 10 10 57
    I guess maybe the test still passed, but then there's something wrong when the fastlane try to write the log or test report to the filesystem.

@blyscuit
Copy link
Collaborator Author

@Thieurom

So the newly-added test class (and its filename) should be AppSpec

What is the plan when we include more tests to a growing app? Having one AppSpec would be too bloated? What do you think if we name the test specs by the name of the feature flow for example CoinDetailSpec, LoginSpec, etc?

[Assert] Unsupported enumeration of UIWindowScene windows on non-main thread. then crashed

This is the same issue with

the logs showed many Main Thread Checker issues.

I'm taking a look at it. Could be because parallel testing 🤔.

CI (GitHub Action) slowly and failed

I will try with a failing test on the CICD of this project.

@blyscuit
Copy link
Collaborator Author

@Thieurom Main Thread error comes from Quick(6.x) and Nimble(11.x) newest versions. This error does not happen in when running KIF with XCTest or Quick(5.x). To solve this we add @MainActor to Quick spec


    override func spec() {

        describe("a Home screen") {

            describe("its open") {

                it("it shows its ui components") {  @MainActor in
                    self.tester().waitForView(
                        withAccessibilityLabel: Strings.Home.Title.text
                    )
                }
            }
        }
    }

but this will require adding MainActor to all KIF functions. Alternatively we can


    override func spec() {

        describe("a Home screen") { @MainActor in

            describe("its open") {

                it("it shows its ui components") {
                    self.tester().waitForView(
                        withAccessibilityLabel: Strings.Home.Title.text
                    )
                }
            }
        }
    }

but it will result in the warning.
Screen Shot 2023-01-16 at 14 58 14
Personally I prefer the last way but devs will have to ignore the error 😭 .

I leave this to the team to decide 🙏

@Thieurom Thieurom modified the milestones: 0.7.0, 0.8.0 Jan 18, 2023
@Thieurom Thieurom removed this from the 0.8.0 milestone Jan 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants