Blog Post

What Is Dependency Coverage?

July 22, 2022 Cassie Gatton

Conveyor belt

Every modern software application consists of multiple connected components. As with a puzzle, you add external libraries, packages, and modules to your product to form a bigger picture.

In this context, a metric like code coverage is extremely useful, but often it can be limited.

Suppose you wrote multiple quality tests and achieved 80 percent coverage for your project, but now you need to add an external library to it. How do you prevent a vulnerability in this library from breaking your project? What other dependencies in your code could evade the checks of code coverage and break it?

In this article, you’ll learn about the potential dependency threats to your application and best practices you can follow to shield your product from them.

 

Why Do You Need Dependency Coverage?

Dependency coverage is useful because of the main principle of modern software development: your application is not a monolithic block but a system interconnected with dozens of other libraries, applications, and modules. If you don’t test these dependencies, you’re missing out on multiple opportunities for improvement.

Testing provides these benefits:

  • Understanding possible points of failure: If you don’t test your project dependencies, your app might break for reasons you didn’t anticipate, such as a dependency library containing malicious code or unit tests relying on other broken unit tests.
  • Deploying with more confidence: The better you understand your code and its vulnerabilities, the faster you can deploy, because you’ll know exactly what to test thoroughly before sending code into production.

How Do You Track Dependency Coverage?

The following are some best practices you can adopt at various points of your application to create a resilient, well-tested environment with dependencies.

 

Map Your Dependencies

As a first step, you should aim to always keep your project’s external libraries under control. For each dependency, you can note basic documentation explaining what it does, which version your project uses, and any relevant links that could be useful to your peers.

This approach gives you some advantages:

  • The documentation shows your team the current state of your project’s external libraries, so everyone can tell when a library should be updated—for example, if security patches have been created for the latest version.
  • You can use the documentation to keep track of which libraries were updated, consequently showing which parts of the app you should test to verify that everything is working as before.
  • The knowledge in the documentation is available to your whole team. Otherwise, you risk limiting all that knowledge to a single developer, who could then leave the organization and expose your product to risk.

If your project contains far too many dependencies to be mapped manually, you can use a specific command from your favorite package manager. For example, with npm, you can visualize all your project dependencies in the command line by typing:

npm list

Create Automatic Updates

New security issues with libraries are discovered every day. As a developer, it can be hard to keep track of all the updates needed to protect your project. To solve this vulnerability issue, you can automate your dependency updates. A tool like Dependabot automatically scans all your dependencies’ vulnerabilities and updates them to protect you from potential malicious attacks.

Avoid Cross-Dependent Tests

As a rule of thumb, your unit tests should never depend on each other. If they do, or if they must run in a specific order because of external dependencies, then you need to change your tests.

For example, if one unit test creates a student entry in a database for a school app and another test deletes this student, the second test depends on the first test’s result.

Unit test frameworks don’t guarantee that your tests will run in any particular order, so any type of cross-dependency you create is going to be dangerous. It could also translate into a hard-to-track bug that costs you extra time and effort.

If your unit tests are independent, your testing suite gains multiple advantages:

  • Easier-to-read tests: If your tests are standalone units, it’s easier to understand them without needing to check anywhere else in the app.
  • Tests that fail individually: If your tests have dependencies between each other and one of the tests fails, is the problem inside that test or in one of its dependencies? Having independent tests helps you see exactly what’s breaking.

 

Be Careful of Failing External APIs

In 2020, a bug in the Facebook SDK caused many apps depending on it to crash. This is an example of an external dependency causing your app to break.

External dependencies are all those dependencies you don’t have full control over, like npm packages, SDKs, or APIs. There are steps you can take to protect your product from bugs in an external API:

  • Never assume it’s returning the correct data: The API might not always return the data you asked for. Run some validations on the returned JSON to prevent possible crashes.
  • Consider adding schema validation to your API calls: If an API’s response is subject to some structural changes, your app won’t be compatible with it anymore. You can use schema validation for your calls, preventing unwanted parse errors and bugs across your app.

 

Choose Good Dependencies

The best way to ensure no dependency ever breaks your project is easy: don’t trust any external resource. Unfortunately, this is a difficult approach that will likely guarantee your application is never released.

For a better approach, don’t just test your dependencies—learn how to choose the right ones.

When it comes to integrating a tool, library, or package inside your app, look for the following trust signals:

  • Good documentation: This is the first signal of professional developers who care about the product they are delivering.
  • Code coverage metrics: Code coverage is not only a great metric to better understand a project but also a commitment to greater quality. You can look for coverage metrics in the dependency you want to use as a way of assessing the tool’s reliability.
  • Maintenance and open issues: Is the tool in question still being maintained? Are there dozens of open issues still unresolved? A tool that’s constantly undergoing maintenance will help you avoid annoying bugs along the way.

 

Conclusion

The final version of your application is the result of many pieces joined together. Just as with an assembly line, you add external libraries, packages, and modules to your application to make it work the way you want. Unfortunately, while dependencies make your project possible as a developer, they can also expose your product to various vulnerabilities.

To amplify your test coverage and reporting, you can use Codecov, a dedicated tool for monitoring the code coverage of your project. Codecov works with languages including Python, JavaScript, C, and TypeScript; tools including GitHub and GitLab; and all major cloud platforms and CI/CD integrations to provide code insights and actionable metrics. You’ll be able to develop and deploy with confidence.

For more on how Codecov can help you, check the documentation.

Before we redirect you to GitHub...
In order to use Codecov an admin must approve your org.