Testing in Depth. (Also, please don’t use undeclared dependencies.)

Robert Fink
9 min readintermediate
--
View Original

Overview

The article discusses a specific bug related to undeclared dependencies in a software product, illustrating how this oversight was caught by a continuous delivery system named Apollo. It emphasizes the importance of dependency hygiene and the practice of 'Testing in Depth' to ensure software reliability.

What You'll Learn

1

How to prevent bugs related to undeclared dependencies in software projects

2

Why continuous delivery systems are essential for managing software releases

3

How to implement effective testing strategies that include both pre-release and post-release monitoring

Prerequisites & Requirements

  • Understanding of dependency management in software development
  • Familiarity with Gradle as a build system(optional)

Key Questions Answered

How did a bug related to undeclared dependencies escape testing?
The bug escaped testing because the DatabaseClient used OkHttp classes without declaring it as a dependency. This reliance on a transitive dependency was not caught during integration tests, which used an in-memory database that did not trigger the OkHttp code path.
What is the role of Apollo in managing software releases?
Apollo manages software releases by monitoring health checks and rolling back deployments if issues are detected. It allows for controlled upgrades across different stacks, ensuring that any problematic releases are quickly recalled and fixed.
What are the key components of Testing in Depth?
Testing in Depth involves layering various testing techniques, including unit tests, integration tests, and post-release monitoring. This approach enhances software reliability by ensuring that different aspects of the system are validated at multiple stages.
How can dependency hygiene be maintained in software projects?
Dependency hygiene can be maintained by using Gradle plugins that enforce explicit dependency declarations, prevent duplicate classes, and alert developers about unused dependencies. This helps avoid issues like the one discussed in the article.

Technologies & Tools

Some links below are affiliate links. We may earn a commission if you make a purchase.

Build System
Gradle
Used for managing dependencies and build processes in the software project.
Continuous Delivery
Apollo
Manages deployment and monitoring of applications to ensure reliability.
Rpc Library
Conjure
Used for making calls to web services in the product.
Database
Atlasdb
Used as a remote database service in the production implementation.
Database
Cassandra
Used as a remote database service in conjunction with AtlasDb.

Key Actionable Insights

1
Implement explicit dependency declarations in your projects to avoid reliance on transitive dependencies.
This practice helps prevent bugs that can arise from changes in libraries that are not directly controlled by your codebase, as illustrated by the bug in the article.
2
Utilize continuous delivery systems like Apollo to automate monitoring and rollback processes.
Automating these processes can significantly reduce the risk of widespread outages and improve response times to issues in production environments.
3
Adopt a layered testing strategy that includes both in-vitro and in-vivo testing.
This approach allows for comprehensive coverage of potential issues, balancing the speed of development with the need for thorough testing.

Common Pitfalls

1
Relying on transitive dependencies without declaring them can lead to runtime errors when underlying libraries change.
This happens because the build system may not catch the absence of a direct dependency, leading to issues like ClassNotFoundExceptions when the transitive dependency is removed or altered.

Related Concepts

Dependency Management
Continuous Delivery
Testing Strategies
Software Reliability