So this question of mine all began when I started to do unit testing for a simple 2 line of postNotification
and addObserver
. From this similar question here you can see that to make it testable you need to add ~20 lines & part away from the common way of writing your code.
Facing this problem was actually the first time I understood the difference between Unit Testing and TDD. Unit testing is easy if your code is testable ie if you are following the TDD mindset. Next I was brought to how can I write testable code, which I didn't find much guidelines, every tutorial simply just jumps into writing a unit test. Apple own documentation has nothing for this.
My initial thought was that I need to aim for 'functional programming' and write my functions in a pure function way. But then again this is very time consuming and may require lots of refactoring in existing codes or even for new projects lots of added lines and I'm not even sure if that is the correct approach. Are there any suggested guidelines or standards for writing testable code in an easy way?
What I know myself already: I know that you shouldn't write any code, unless there is a test for it to fail, so basically I have to write the test first and as soon as I get an error, even a compiler error then I would have to switch back to the actual class being tested write whatever necessary and make my test code not give any errors , then switch back to the test class and continue writing my test and fixing compile errors until done. Then run the test and see if it checks what I want it to check.
For all tests I should make sure that my tests would pass and fail exactly where I expect to fail ie the test would pass when it's expected to fail.
What I don't know is how can I smoothen the process in a more easier way.
I am not asking for how to write a testable code for NSNotificationCenter, I am asking for general guidelines for writing testable code.
Click on the Test Navigator tab in the Xcode Navigator (the left-most window). This tab can also be reached by pressing ⌘ + 6. In the bottom left corner you can add the test target by pressing the '+' button. Follow the instructions on the screen and voila: You are now ready to write your first unit test.
If a Swift module is compiled with “testing enabled” it allows us to import that module using the @testable annotation to alter the visibility of our code. Classes and their methods that are marked as internal or public become open , which allows subclassing and overriding in tests.
Use the XCTest framework to write unit tests for your Xcode projects that integrate seamlessly with Xcode's testing workflow. Tests assert that certain conditions are satisfied during code execution, and record test failures (with optional messages) if those conditions aren't satisfied.
This is a rather large question, and one where developers' views sway to very different directions. It is also important to note that making code testable is in many essential ways not a Swift specific question: a lot of what makes you able to write testable code routinely and conveniently actually relies on you following some fundamental, generally applicable principles. Often test driven design practices help you indirectly, by validating you have followed practices that make executing your code via tests plausible, beside bringing you other programmer productivity and reliability benefits. So, unfortunately writing testable code is not a question of learning some mechanical tricks of working with Xcode, rather than often a proof of you having designed and planned the programs and libraries you write keeping to some good practices.
I'll do my best to link below to some Swift specific resources to demonstrate the more general principles I tend to myself follow to make my code testable.
Making your code testable is often a side effect of following sound object oriented design principles.
Following a sound object oriented design is often itself the side effect of good higher level architectural decisions. Basically, think early and often about the kinds of types you plan to introduce in the object graph of the program. What are the roles and dependencies between them? Are any of the dependencies in your object graph hard to meet or correctly construct when executing your code from different contexts (e.g. from UI code vs a unit test)?
The above points raised are in no way Swift specific, and I would expect not terribly controversial claims. Swift does however also offer language features that also help you write reliable, bug free code, in part as these language features help you make your code testing friendly. Here's a few of good Swift practices:
Again, this question is large and I am really just scratching the surface with my answer, in order to make the point that there is no single magic bullet to testability – it's something you achieve as a result of following many best practices when designing your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With