Using shared examples and shared context in infrastructure testing

During the last few months we've been heavily adding unit testing to our Chef codebase. In this article I will explain the benefits and how to use shared_examples and shared_context in ChefSpec testing.

ChefSpec isn't anything more than an extension of RSpec for unit infrastructure testing. We have all the resources available to express assertions that RSpec provides, I will focus on two of them.

Shared Examples

Shared examples let you describe behaviour of types or modules. When declared, a shared group's content is stored. It is only realized in the context of another example group, which provides any context the shared group needs to run.

You can use a shared example to group common assertions that can be reused for different use cases in your test suite. There are two relevant pieces of syntax used:

To define the shared example you just use shared_examples and pass a block.

To include a shared example in your testing you can use one of the following keywords:

include_examples'name'# include the examples in the current contextmatchingmetadata# include the examples in the current contextit_behaves_like'name'# include the examples in a nested contextit_should_behave_like'name'# include the examples in a nested context

Let's try a small example: assume that all of your servers require a few base packages installed. For the sake of this example let's say that it's just htop and nmap. But your web servers also require postgresql-9.5 and your database servers also require postgresql.

There is an alternative way of declaring shared contexts via matching metadata. You can learn more about shared contexts by going to the official docs.

Summary

Shared context and examples are a good, DRY way of reusing useful information for your tests and to reuse the tests themselves. You can take advantadge of both to have a cleaner, more efficient, and wider test suite.