Scribe-iOS
Scribe-iOS copied to clipboard
Create functional testing files and ci process
Terms
- [x] I have searched open and closed issues
- [x] I agree to follow Scribe-iOS' Code of Conduct
Issue
Testing for Scribe and a continuous integration process would be very helpful to assure that pull requests can merged without issue. Discussions of best practices as well as how best to integrate the process into pull requests would be a first step in this issue. This would be followed by writing tests for a baseline, and then adding a ci.yml
file to a workflows
directory in Scribe-iOS/.github.
The issues with Scribe not functioning as on Simulator means that testing should be a priority, potentially even for the next release. Specifically #96 seems difficult to test for on Simulator. One option going forward would be to integrate a device testing service like Browserstack, which is available free for open source. There's also the ability to add GitHub Actions integration, which then could function as a part of the general CI process.
Currently reviewing the following documentation @andrewtavis. Docs:
- Apple's XCTest docs
Articles:
Will have a brief summarisation by EOD. Also, checking out Browserstack. Thank you for creating all the issues 😄 🚀
You’re welcome for the issues, @SaurabhJamadagni! We can talk tomorrow if more are needed 😝😅😊
And thanks for looking into all this :) I’ll assign the both of us for research and implementation 🙃
Hey @andrewtavis, sorry for the delay but here's a brief summarisation of the basics from the articles and docs:
-
We will first need to define a testing target. Each keyboard should get its own testing target, something similar to what we had seen while trying to debug. We were unable to run a breakpoint if it was directed at the wrong target.
-
A subclass of XCTestCase contains test methods to run in which only the methods starting with “test” will be parsed by Xcode and available to run.
- The naming convention for the testing class is "ClassnameTests".
- The functions are by convention named as "testWhatTheTestShouldAssert"
-
Testing is primarily using the XCAssert function. Although, vanilla XCAssert won't give the most clear explanation of why a test failed. Using the right XCAssert method can help fixing the problem easier.
-
They might produce the same outcome but test for different things.
-
XCTAssertTrue
,XCTAssertFalse
,XCTAssertNotEqual
,XCTAssertEqual
,XCTAssertNil
andXCTAssertNotNil
are some of the commonly used XCAssert functions.
-
-
For each unit test function you will see an empty diamond shape in the gutter on the line of the function declaration. Clicking this diamond will run the specific unit test.
-
Parameters used in multiple test methods can be defined as properties in your test case class. You can use the
setUp()
method to set up the initial state for each test method and thetearDown()
method to clean up.- An example could be generating a user defaults instance to use for unit tests. Doing so ensures you’re not manipulating the standard user defaults used during testing on the Simulator.
- These functions are called before and after each of the test functions, respectively. This allows us to set up prerequisites before the tests are being run and to clean up any mess we’ve made after the completion of each unit test.
-
Use @testable which is a flag at compilation to access private declarations at testing without having to modify source code. (I don't completely understand how to use this yet, but thought should list anyway. Will update if I get more information)
- This flag goes is attached to the import statement of a target. Ex:
import XCTest @testable import TestTarget
-
What I learned about Test Driven Development (TDD) is that whatever function we want to test, the first step would be list out all possible cases before going to implement the logic. This includes listing out the extremities as well.
I came across a library known as Nimble, which is apparently popular for asserting instead of the standard XCAssert functions. Going through it and will check if there are any advantages to using it over the native functions.
Thanks, @SaurabhJamadagni! Will read into this all a bit when I’m back 😊😊
Hi @andrewtavis, I want to work on this issue :)
Issue #8! Talk about getting to some early issues these days 😊 Thanks so much for your help here, @vickcoo! I agree with you that it makes total sense to work on this so that we can verify that further changes don't break things. Great thinking :)
Please let us know if there's anything we can do to support! As we discussed, maybe we can find a simple first test to write and set up the process here, and then we can make new issues for the other tests. I'm sure that maybe @fabulouiOS-monk would also have interest in working on tests once we get a basic process up and running? :) We can write to the iOS room on Matrix and check with the community too 😇
What are you thinking for the first test, @vickcoo?
Ready the discussion here would be a good first step, and let me us what you think next steps should be :)
Maybe we can start from here Extensions.swift. Let's set things up and write simply unit tests to make sure everything is working well. Or you could suggest where would be a great place to start.
And I see there are so many files without any Class or struct, Just the variables and functions. Which could make our testing a little bit harder.
If we will require (obviously we will require those) then mocking the values and function returns will be harder.
I suggest we write unit test cases one by one and handle the issue (refactoring and writing them inside of class or struct) as per the requirement. Well, that will be a hell lot of work but need to do it at some point in time.
@fabulouiOS-monk you're right! I saw the code, and it left me very confuse. So, should we write unit tests for the code that has class/struct first, or should we handle the code without class/struct first?
I think doing extensions first makes sense, and does it work to do the refactor and write the test in the same PR? So we'll start with any changes that the extensions need and add the extension unit tests to a new PR workflow for this issue, and then from there we'll plan out the changes and make individual refactor and test issues?
Sorry for the mess, by the way! Honestly some of this is just me not knowing any better and not having folks to discuss it with :) Happy to have you both here to work on this 💙
Yup @andrewtavis, thats the right way to go ahead. We will start with small files which are in class and structs, If needed on the go we will also refactor the required file.
@vickcoo lets start with this and ping me in Matrix personally. It will be easier for conversation.
Working PR based tests! What are you two thinking for the next files to look into? :)
Hi @andrewtavis, I think we can work on the same directory(KeyboardBase), then choose the file that has a complete class or struct for the highest priority, like this KeyboardStyling.swift
@fabulouiOS-monk what are you thoughts on this, perhaps you have another suggestion
Hi @andrewtavis, I think we can work on the same directory(KeyboardBase), then choose the file that has a complete class or struct for the highest priority, like this KeyboardStyling.swift
@fabulouiOS-monk what are you thoughts on this, perhaps you have another suggestion
Yes, @vickcoo we can go ahead as per your suggestion. I was looking into it and found two classes: CommandBar & ScribeKey
All sounds great, @vickcoo and @fabulouiOS-monk! Awesome that such key parts of the keyboards will be tested :)