How I Transformed Struggles into Confidence with Automated Testing in Android | by Rahul Raveendran V.P | Feb, 2025

How I Transformed Struggles into Confidence with Automated Testing in Android | by Rahul Raveendran V.P | Feb, 2025

Photo by Danial Igdery on Unsplash

Are you familiar with writing automated tests for your Android app? If so, this blog post might seem a bit basic. But for those new to automated testing or struggling with it, I hope my experience will be useful and inspiring.

In this post, I’ll share my journey as an Android developer with over 10 years of experience. I’ll discuss the challenges I faced implementing automated tests for an Android SDK and how I overcame them. By the end, you’ll understand the importance of automated testing and how it can transform your development process.

As an Android application developer with over 10 years of experience, I’ve worked with various tools, from Eclipse to IntelliJ IDEA, and now Android Studio. It’s been quite a journey!

I began my career at a service-based company, building apps for other businesses. Our primary focus was delivering apps quickly with minimal or no crashes. One day, a client asked us to write a mobile SDK/library and emphasized the importance of “writing tests,” which was a new concept for us. We agreed and, with the client’s developer’s help, wrote basic test cases for their library. Afterward, we returned to our usual rapid app development.

Currently, I work for a SaaS company maintaining their Android SDK. The SDK, written in Java, was aging, and keeping up with the evolving Android platform became challenging. Releases were stressful because manual testing took hours, and avoiding regressions became a real challenge. I had considered automated testing before but wasn’t sure how to implement it. Surprisingly, none of my peers used automated testing, leaving me without guidance.

Years later, I decided to rewrite a module in the SDK and was determined to implement automated tests. Learning about it proved challenging due to the numerous testing libraries and their compatibility issues between Java and Kotlin. Since we chose Kotlin for the new module, our tests also needed to be in Kotlin.

Initially, I wrote the feature code quickly and performed some manual testing, which seemed promising. However, once I started writing the test code, the real challenges emerged. AI tools offered some assistance, but their suggestions often led to build errors. Without a solid foundation in automated testing, the documentation only added to my confusion.

Weeks turned into months, and I was on the verge of giving up. Then I discovered Philipp Lackner’s YouTube channel. One of his videos on Android testing completely changed my perspective and provided the clarity I needed.

Philipp highlighted some key issues I faced: a lack of design patterns and high class coupling. The initial Git commit for the SDK was in March 2015. At that time, the focus was on rapid app delivery, and design patterns weren’t a priority. Consequently, although functional, the SDK lacked structured design.

Design Patterns

While rewriting a module for the SDK with automated tests, I chose to implement the repository pattern to address these issues. This pattern involves creating abstract classes with method definitions and implementing these methods in specific classes. For the new module, storage was managed using an SQLite database, benefiting from this more organized approach.

This application of design patterns not only enhanced the code’s structure but also significantly improved its testability.

Here’s an example of my event repository interface:

interface EventRepository {
fun insertEvent(event: Event)
fun deleteEvents(events: List)
fun readOneBatch(batchCount: Int = 100): List
}

Here is a high-level implementation:

class EventRepositoryImpl(context: Context?) : EventRepository {
override fun insertEvent(event: Event) {
// implementation using SQLite
}

override fun deleteEvents(events: List) {
// implementation using SQLite
}

override fun readOneBatch(batchCount: Int): List {
// implementation using SQLite
}
}

Reducing Class Coupling

Class coupling was another challenge. For example, I had an EventManager class responsible for storing events and creating batches for API calls, with storage managed through SQLite tables. Initially, the code looked like this:

class EventManager(context: Context) {
var eventRepository: EventRepository = EventRepositoryImpl(context)
}

This setup made testing difficult because EventRepositoryImpl was instantiated directly within the EventManager class, resulting in tight coupling that hindered the use of a mock implementation for tests. To resolve this, I implemented dependency injection to decouple the classes. Simple constructor-based dependency injection proved effective:

class EventManager(eventRepo: EventRepository) {
var eventRepository: EventRepository = eventRepo
}

With this approach, I could create a fake version of EventRepository that uses a simple List to handle operations like insert and delete. This method also eliminated the need to pass a Context for initialization, making it easier to test without relying on a real device.

Lessons Learned and Final Thoughts

After watching Philipp Lackner’s video on Android testing (embedded above), I discovered valuable libraries for testing Kotlin code, including those for handling coroutines. It took me nearly six months to reach this point, but now incorporating tests is a key part of any new changes in the SDK. Looking back, I wish I had started this journey sooner.

Implementing automated tests has fundamentally changed how I approach Android development. It was challenging, but the confidence I now have in my code is truly rewarding. I encourage every developer to start writing tests as early as possible. It might be tough initially, but the long-term benefits are certainly worth the effort.

Happy coding! 🎉

— –

I’d love to hear about your experiences with automated testing. Have you faced similar challenges? Feel free to share your thoughts in the comments below!

About sujan

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.