How to Dramatically Improve Testability for Mobile App Development – Part 1
How to Dramatically Improve Testability for Mobile App Development
Part 1: Why Yesterday’s Approach no Longer Fills the Bill
Software quality is only as good as the methods used to develop and test the code. Thorough testing, if not performed well, can be very resource inefficient and therefore may not validate the design. At Syncro Medical, we are constantly looking for ways to increase overall medical software development efficiency, and that includes the efficiency and accuracy of testing approaches. bring their own set of challenges when requiring a confident testing model. Applying a desktop design pattern that supports solid testing is often difficult, but with the proper approach, it can be applied effectively. Code that is built from the top down with a thorough testing-capable design is more stable and maintainable, and all-in-all more valuable to our clients and to their customers.
“Code that isn’t tested doesn’t work. This seems to be the safe assumption.” These words from Kent Beck’s book, Test-driven Development: By Example, are good words to live by as a software developer. If you (or even better, others) haven’t tested your code, how can you know that it will work in all situations when it gets into the hands of your users? And if you don’t continually test, how do you know it still works after you’ve made changes to your code, even if those changes are to seemingly unrelated parts of your system? This is particularly important for a Mobile UI where there are many ways in which the user can interact with code and many of the error conditions that can occur are difficult to reproduce. You need a way to test your code that is repeatable and can simulate all of the error conditions the user might encounter.
The Importance of Unit Testing
Typically, Unit testing has been the method of choice. Unit tests are small test methods that isolate components of the code by emulating the dependencies and testing the behavior of the components by manipulating the inputs and observing the outputs. By emulating a component’s dependencies, a unit test can test all conditions the code might operate under, including error conditions that would be difficult to reproduce in a live system. Continuous Integration Systems (such as TeamCity) can build and run the unit tests every time new code is checked into your source code repositories, giving you confidence that your existing code still works as new code is implemented.
However, testing a mobile medical app UI can be a challenge. For unit testing to be effective, it has to be designed into your system. Complex components with many responsibilities, dependencies, and internal states are difficult to test. The developer must break down the design into very small components with limited responsibilities and clearly defined inputs and outputs. The dependencies of the components should be accessed through interfaces, allowing those dependencies to be emulated or “mocked” so that the component under test can be isolated and controlled.
The Classic MVC Design Pattern is of Limited Value
Most of the books, tutorials, and documentation for Android and iOS promote using the Model-View-Controller (MVC) design pattern to separate the View from the business logic in the Model. This pattern does a good job of providing a separation of concerns between the View and the Model, and therefore greatly increases the testability of the business logic in Model layer. But there is a serious shortcoming – it ignores the fact that the UI has business logic of its own that lives in the Controller, and that the Controller, by its nature, is difficult to test.
In general, the MVC design model expects a mostly passive View, or UI. The View relies on the OS-provided methods and widgets. The Controller in an MVC design is usually tightly coupled with the View objects, such as a textbox or button, and with the UI platform APIs. The Controller typically retrieves data from the Model and updates widgets in the View or connects to events from the widgets and relays them down into the Model. This makes it extremely difficult to test without creating a large number of mocks for the platform objects that the Controller interacts with.
Because of this complexity, software teams often resort to UI automation testing that tests the system as a whole by acting as the user. This is not a replacement for proper unit testing and is often only able to test common workflows and not error conditions. Often as not, the common decision of many software teams is to simply not test the UI. This opens up the code to errors that won’t be found until code is in the hands of your users. In dealing with this situation, a developer is bound to think, “It would be better if the business logic were separated from the View”.
For several years, Syncro Medical has solved this problem on desktop applications by using the Model-View-ViewModel (MVVM) design pattern and Microsoft’s WPF Framework. It relies on a more active View but one that consists of only the UI itself. Testing the UI is therefore limited to verifying the visual and operational elements. All the business logic is behind the View in the ViewModel. The MVVM pattern is a natural fit for WPF applications and it has become very popular with desktop application developers.
But what about Android and iOS? Well, it turns out the MVVM pattern can be adapted to those platforms as well. In Part 2 of this series, I will explain how MVVM works, and share insights about its significant benefits for mobile medical app development and testing.