In this final chapter of the book, we will cover how to test your Chef automation code. It is important to perform testing and verification steps before deploying your Chef code to production to ensure it works as intended.
In nearly all the exercises in this book, we’ve taken care to add sections highlighting how to manually verify that your Chef code is working properly. In this chapter, we’ll show you how to automate this process.
Testing Rationale
Using a configuration management tool like Chef gets you 50% of the way there in automating testing and verification. Because Chef automates infrastructure in a repeatable manner, it inherently makes apps running in these environments more testable. This is why we introduced Test Kitchen so early in the book, in Chapter 5, so that you could see this in action. Throughout the book, you’ve deployed your Chef code to a local development sandbox environment. Using Test Kitchen should give you confidence that if you deployed the same code to a production Chef environment, it will behave in the same manner.
The other 50% of the testing rationale, besides using Chef in the first place, is to be strategic when testing and deploying automation code. Just as it is best to introduce change to application code in small batches, it is also best to introduce change to your infrastructure in small batches. As Figure 16-1 shows, you should work in short bursts, performing a short build-test-deploy cycle. This approach can help ensure that enough testing gets done to result in an infrastructure and application of high quality.
It’s harder to estimate when long, drawn-out development cycles will complete than shorter “baby step” development increments as advocated in Figure 16-1. As Figure 16-2 shows, what almost inevitably happens with long, drawn-out development cycles is that testing is done at the last minute and it ultimately takes longer to deliver a large feature than intended. At the same time, the shorter testing period sacrifices quality, and this can lead to the “throw it over the wall to operations” scenario where applications work fine in development but don’t work in production. Configuration management tools like Chef try to address this problem.
Further, there is a monetary cost associated with finding and fixing bugs in your software and infrastructure code, and that cost goes up the further out in the development cycle you discover issues. Figure 16-3 shows the relative cost of fixing a software bug as development progresses. Your infrastructure code is no different than application code in this respect:
- Requirements
- Design
- Coding
- Development testing
- Acceptance testing
- Operations/production
Finding and fixing issues during the requirements and design phase is not very expensive. However, the cost goes up the further out in the development lifecycle you go. When you wait to find bugs after they have been coded, the costs are 20 times to 50 times greater than if you had caught them earlier. During the production phase, the cost is 150 times greater.
This graphic serves as a good reminder of how you should always approach a Chef coding project:
- Code right the first time, because it costs a lot more to fix things later.
- Find bugs and issues as early as possible, ideally before they ever get in, or at least as close to the time of coding as possible.
- Make changes in small batches—the smaller the change, the less likely you are to introduce a lot of new defects. It’s also easier to test in small batches.
Chef includes testing tools that support this approach. As Figure 16-4 shows, Chef provides multiple testing tools specialized to give you feedback on issues with your code at the earliest possible time during the cookbook authoring process.
There are multiple tools because each is tailored to run in a particular cookbook authoring phase. Following is a brief overview of each tool and when you use it:
- In your text editor when you type:
- Before you deploy to a test node:
- After you deploy to a test node:
For those using Chef Client, you will need to install some additional gems to support testing. Run the following to install the required tools for this chapter:
If you’re using the Chef Development Kit, you’re fine, these Ruby gems have already been installed for you.
Revisiting the Apache Cookbook
For people new to automated testing, Serverspec is the most easily understood tool, so we’ll start with it first. We will test it by revisiting a cookbook we created in Chapter 7. We’ll be adding tests to this cookbook in this chapter.
NOTE
We are covering Serverspec v2 syntax.
Generate a cookbook called
apache-test
.
Chef Development Kit:
Chef Client:
Edit the .kitchen.yml as shown in Example 16-1. Use the
chef_zero
provisioner and our favorite basebox image. Additionally, configure a private_network
with an IP address of 192.168.33.38
so you can access the website from your host development workstation like you did in Chapter 7.
Make sure there are no syntax errors in your .kitchen.yml by running
kitchen
converge
:
Create a
default
recipe with the same code we used in Chapter 7.
Create an ERB template for the index.html file.
Chef Development Kit:
Chef Client:
Let’s do a little something new with the index.html.erb template. In Introducing the Template Resource we learned that the ERB template processor looks for tags such as
<%= %>
in .erb files, evaluates the expression within the tag, and returns a string as output:
If the tag does not have an equal sign, it is evaluated as a scriptlet instead of a string. Within Chef templates, this mechanism is used to add conditional logic. For example, take a close look at this ERB template:
TIP
Pay close attention to where
<% %>
is used and where <%= %>
is used.
On my test node, which has three network interfaces—
lo
, eth0
, and eth1
—the scriptlet will render the following output:
The lines in the ERB template without an equal sign
<% %>
are evaluated as scriptlets; the expression is evaluated but not rendered in the output file as a string. Then we use the ERB tag with an equals sign <%= %>
to print out a line in the resulting output each time we run through the conditional logic.NOTE
In order to determine that
node['network']['interfaces']
was the correct variable syntax, we inspected the output of ohai
, looking for the values that we wanted to display.
In your cookbook, edit index.html.erb as shown in Example 16-3. We’ll use a variant of the preceding logic that prints out each interface name on the node and its IP address, using more idiomatic Ruby and some bare-bones HTML.
NOTE
This is admittedly horrible HTML! But it will render readable output, which is our only goal. Thankfully, this is a book on Chef, not HTML.
Perform a final
kitchen converge
to ensure there are no syntax errors in your code:
Verify that the website functions as intended by visiting it at
192.168.33.38
. It should render as shown in Figure 16-5. Test Automation with Serverspec
In the last section, we verified that our cookbook worked by running
kitchen converge
and verifying that the website worked by checking it manually. Let’s automate our website verification process by writing some tests in Serverspec and running the tests with Test Kitchen.WRITE YOUR FIRST SERVERSPEC TEST
By default, Test kitchen will look in the test/integration subdirectory for test-related files. Serverspec looks for its own files a few more directory levels below test/integration. First there needs to be a directory name underneath test/integration that matches the suite name:
As Figure 16-6 shows, the name of the suite can be found in the
suites:
stanza of the .kitchen.yml. default
is the suite name that is initially generated. Although not covered in this book, you can use the suite capability of Test Kitchen to run sets of tests with different run lists and attributes, perhaps exercising conditional functionality in your cookbook.
In our case, the suite name is
default
, so create a directory for that now under the apache-test cookbook root.
Linux/Mac OS X:
Windows:
Further, we need to create a directory underneath test/integration/default to tell test kitchen that we want to use the
serverspec
test plugin. Rather than specifying this in the .kitchen.yml file, Test Kitchen infers this from the directory structure underneath test/integration. Create the test/integration/default/serverspec directory now.
Linux/Mac OS X:
Windows:
By convention, Serverspec expects files containing test code to end in the suffix spec.rb. Create the file default_spec.rb in the test/integration/default/serverspec subdirectory of your cookbook, as shown in Example 16-4.
There are three major components to the spec.rb file, which we’ve labeled 1, 2, and 3:
- The
require
statement is used to load the gem library forserverspec
, so we can reference Serverspec classes and methods, such as theset
method. - The
set
statement lets us configure howserverspec
runs. In this case, we set the:backend
property to:exec
to tellserverspec
that the test code will be running on the same machine as where it is being evaluated. - Tests are written using the RSpec DSL using
describe
andit
statements. In this case, we’re using the RSpec DSL to write a test that checks to see if our website is listening on port 80 using the TCP protocol (the standard port/protocol for an HTTP website).
We’ll go over the RSpec DSL and test syntax in more detail in RSpec DSL Syntax. For now, just accept that this is the syntax to specify a test that checks to see if something is listening on port 80.
In order to run this test code, you first need to make sure all the necessary gem files are loaded on the test node. We do that with the
kitchen setup
command. Go ahead and run kitchen setup
now:
When the
kitchen setup
command runs, it inspects the directory structure in the test/integration/<suite>/<plugin> subfolder on your development host. Test Kitchen will then load any plugins required for testing in your sandbox instance as indicated by the <plugin> directory name. Because we created the directory subfolder test/integration/default/serverspec, Test Kitchen makes sure that the test node has all the necessary libraries and gems for running serverspec
tests.
Once the test node has all the appropriate test libraries, you can run your tests using the
kitchen verify
command. Do that now. Barring any errors in your code syntax, the output should successfully indicate that the website is running and responding on port 80:
You can use these RSpec DSL test statements to express checks in code that you would do manually to verify that your cookbook is working.
However, did this test really do anything? Let’s verify this by temporarily disabling the website on the test node and running the test code again.
Log in to the test node with
kitchen login
, stop the web server with service httpd stop
, and exit
back out to your host development workstation command prompt, as shown in the following code block:
Run your test again using
kitchen verify
(you only need to run kitchen setup
once to initialize the configuration on the test node). This time, it should report that the test failed, which is exactly what should happen:
So yes, our test is actually performing checks against the live configuration on the test node.
Before we finish this section, go ahead and run
kitchen converge
again to restore the configuration back to what it should be. During the Chef run, the Chef engine will detect that the httpd
service is not running and start it up again:RSPEC DSL SYNTAX
Before we continue learning more about how to use Serverspec, let’s go over some of the fundamentals of the RSpec DSL syntax, so you know the basics of the Serverspec test syntax.
The RSpec DSL uses a
describe
block to contain a group of tests. A describe
block has the following form:
The purpose of the
describe
block is to group tests in a meaningful manner and describe the entity or thing being tested. The description is just a string passed as a parameter to describe
. This string serves as documentation for human beings to read in the test output. In Example 16-4, we used the following describe
form to note that we are testing our website:NOTE
Under the hood, the RSpec DSL creates a Ruby class in which to group tests.
The actual tests are contained within an
it
block inside a describe
, which needs to be in the following form:
The
it
block also accepts a string for documentation on the specific check that will be performed. For example, in Example 16-4 we supplied the string responds on port 80
to indicate that our test will be checking to see if the website responds on port 80, the standard HTTP port:
As of RSpec 3.0, the version of RSpec that ships with current versions of the Chef Development Kit and Chef Client, the tests themselves should be written in expect form. Here’s what expect form looks like:
A resource (also known as a subject or command) is the first argument for an
expect
block, and it expresses the “thing” to be tested. Testing frameworks such as Serverspec and ChefSpec supply custom resource class implementations that perform a wide variety of checks.
A matcher is used to define positive or negative expectations on a resource, via the
expect(…).to
and expect(…).not_to
forms, respectively. These are also supplied as custom class implementations in testing frameworks.
In Example 16-4, we used the
port
resource and the be_listening
matcher with the parameter tcp
to check to see if the website is listening on port 80 over TCP:
How did we know about this
port
resource and the be_listening
matcher? We referred to the Serverspec test framework documentation listing the resource and matcher classes it provides. See the Serverspec documentation. As of this writing, click on the Resource Types link at the top of the page, and you will see links to all the Serverspec custom resources, as shown in Figure 16-7.
When you click on a resource, you’ll see more detail on all the matchers available, as shown in Figure 16-8.
As you can see from this documentation, you’ll also encounter a legacy RSpec form that was used prior to RSpec 3.0: the should form. The should form was deprecated with RSpec 3.0, because it can produce unexpected results for some testing code edge cases. However, some sites, such as the Serverspec documentation site, haven’t been updated.
Figure 16-9 shows how you can map old documentation in should form to expect form. With should form, the
resource
is in a describe block around the it
clause. With expect form, this is a parameter passed to expect. You can also see how the matcher form differs. With should, expectations are expressed as should or should not, for positive and negative expectations, respectively. With expect, expectations are expressed as the chained methods .to
or .not_to
. Finally, in should form, matcher parameters are expessed using a chained .with()
syntax, whereas in expect form, it is just a parameter to the matcher.MORE SERVERSPEC RESOURCES
Common code can be moved to a file called spec_helper.rb. We only have one file with tests in our example, but imagine there are multiple files. Create a spec_helper.rb as shown in Example 16-5. Notice that the file contains the first two lines from default_spec.rb. Those lines would need to be repeated in every file that contains tests.
Now that you have a spec_helper.rb file, modify default_spec.rb to use the
spec_helper
. Change the require
statement and remove the set
line, as shown in Example 16-6.
Rerun
kitchen verify
. You should notice no net change in the tests. It should still report that one example succeeded.
Although it is a little silly to use a spec_helper.rb file in this contrived example, we hope you see how this file could be used to contain any duplicate code between multiple files with tests.
You can add more than one example with tests in a
describe
block. Normally, there will a handful to perhaps a dozen. Let’s add one more example to default_spec.rb.
Although we’ve written one example that checks to see that our website is responding on port 80, we don’t really know if it is serving up the correct content. Let’s write an example that inspects the website output to see if it seems OK.
If you look at the Serverspec documentation, you’ll find that there isn’t an obvious resource that seems to do what we want. In cases like this, Serverspec lets you run arbitrary command lines via the
command
resource as shown in Figure 16-10. We’ll use the command
resource to run a curl
command to inspect the website output, just as we did in Chapter 7.NOTE
Add a new example to default_spec.rb as shown in Example 16-7. By running the
curl localhost
command, you can inspect the HTML output of the website to ensure that it is working correctly.
Using the
stdout
attribute of the command
resource, we can take a look at the output of the curl
command returned on standard output. It is a convention that programs generate their output to two different standard file handles: stdout
and stderr
, for regular program output and errors, respectively. This way, other computer programs can open these file handles and inspect the contents in an automated fashion. Our example does not care about any errors happening on stderr
because getting notified that an error happened through Ruby exceptions is enough for test code. This error exception generation process happens automatically in Serverspec. We only care about the program output being generated on stdout
.
The results of running
curl localhost:80
are returned to our example code as a string. We use a feature of Ruby called a regular expression and the match
RSpec matcher to search for content in the output generated by curl
. In Ruby, strings containing regular expressions are enclosed by forward slash characters (//) instead of the usual single quotes ('') or double quotes (“”).
A regular expression is a special string format that is used to specify a search string. In this case, we use a regular expression to search for the string
eth1
in the program output. This seems like a reasonable and simple way to check that our website is working. It isn’t likely that the string eth1
would appear in the output otherwise. Using the string eth1
also implicitly checks to make sure that the vagrant box had its eth1
adapter enabled, which is another assumption we’d like to check as well. When there are opportunities to implicitly check more than one condition in your tests, take the opportunity to do so.
There’s a great website for learning more about regular expressions in Ruby. You can use this website to check regular expressions against test strings. Let’s use it to check our regular expression.
First, log in to the node with
kitchen login
and run the same curl localhost:80
command that we will run in our test. The output is shown in the following example. Copy and paste the program output to your clipboard from your terminal window. Then exit
back out to your host prompt:
Once you have the program output in your host clipboard, paste it into the test string field as shown in Figure 16-11.
Once you have a test string, you can enter in any regular expression between the forward slash characters in the Your regular expression field. Once you enter a regular expression, the Rubular site will show you if it would match any results in the test string.
Regular expressions containing strings without any special symbols will match the string itself. For more information about the special characters that can be used, refer to the Regex quick reference section of the Rubular website, below the editing pane. As Figure 16-12 shows, if we use the
eth1
regular expression and the program output contains eth1
, we’ll get a match. And conversely, if the program output does not contain eth1
, we won’t get a match. Thus, we make a match if the regular expression eth1
against the program output of curl localhost:80
on stdout
is a success condition for our example.
Run
kitchen verify
. Notice from the Serverspec report that the second example succeeds. Serverspec ran curl localhost:80
on the node and got the expected regular expression match in the program output:
Just from these two simple examples, we can be fairly certain about whether the website our Chef code produces actually works. Further, when an error occurs, we can more easily determine whether it was a fault in the Apache webserver setup or in our HTML code because we check these two conditions separately.
There’s one more thing we need to cover before you can go about using all of the Serverspec resources in your own test code. Many Serverspec resources require Serverspec to detect information about the test node operating system so it can run the correct commands for the platform. We’ve taken care so far not to use any commands that need this extra support.
The
package
resource is a command that requires Serverspec to detect OS information. Figure 16-13 shows the documentation from the Serverspec site on the service
resource. It can be used to detect whether a package is installed. Behind the scenes, it needs to know what OS is being used so it can use the rpm -q
command on RedHat and variants or dpkg-query
on Ubuntu/Debian to perform this query, for example.
By default, Serverspec tries to automatically detect the OS, which works for most Linux/Unix variants. However, on some platforms you’ll need to override the default OS setting, using the
set
method.
In particular, you’ll need to add the following line to all your _spec.rb files for test code that you plan to run on Windows guests, as Serverspec is unable to automatically detect the Windows OS, as of this writing. The exact
set
commands needed vary by platform. Refer to the Serverspec documentation for more information.
Here’s what a _spec.rb file might look like for Windows, which uses the
set
command to give Serverspec a cue on what OS is running:
In this book, we’re using a Linux variant as our guest OS, so the Serverspec autodetect logic should work just fine. Make sure you check this out on your test platform by using a resource that requires OS platform detection, like the
package
command.
Let’s add an example to default_spec.rb using the
package
command. As shown in Example 16-8, let’s check to see if the httpd
package is installed.
Run
kitchen verify
for Serverspec. The command works fine because Serverspec automatically detected the OS:
If for some reason we need to tell Serverspec that we are specifically running CentOS 6 because of issues with a command, we can add the following
set
line as shown in Example 16-9:
CentOS is in the RedHat family of operating systems. Specifying a
:release
attribute is optional.
When you are not interactively coding tests, you probably want to run
kitchen
converge
, kitchen setup
, and so on all in one fell swoop instead of needing to remember all the individual Test Kitchen actions to run tests.kitchen destroy
(if necessary)kitchen create
kitchen converge
kitchen setup
kitchen verify
kitchen destroy
You wouldn’t want to use this command locally when you are writing tests, as for some cookbooks the process of creating a virtual machine and performing an initial converge can be quite time consuming, and you wouldn’t want the environment automatically destroyed in the end. But Test Kitchen is a perfect command for a continual integration environment such as Jenkins. It’s also a good idea to do a final
kitchen test
run against a clean setup before committing your Chef code to source control.
Go ahead and run
kitchen test
now, so you can see it in action. Plus, it will destroy our test environment. Note that kitchen test
runs all five phases automatically for you:
For more on Serverspec, the Jenkins community cookbook is chock-full of advanced Serverspec techniques. It is a great starting point to learn more about how to perform end-to-end testing of cookbooks.
Test Automation with Foodcritic
Severspec is an invaluable tool for performing end-to-end testing of cookbook functionality. However, spinning up a sandbox instance and performing a full Chef converge can take a long time.
Use the power of Test Kitchen and Serverspec judiciously. Other tools can provide more limited forms of feedback faster. One example of a tool that can provide limited feedback quickly is Foodcritic.
Foodcritic is designed to be used as you are writing Chef code, and it can even be integrated into your editor. Foodcritic provides feedback on your Chef coding style. It does this by performing checks against your code called rules.
You can find all the default rules used by Foodcritic in its documentation, as shown in Figure 16-14. You’ll need to scroll down a bit on the web page to see them.
You run
foodcritic
on your development host instead of in a sandbox environment, so it is fast. Give it a try now. Make sure the root apache-test
root cookbook is your current working directory, and run the following. The results you see might differ depending on whether you are using the Chef Development Kit or Chef Client.
Chef Development Kit:
Chef Client:
As of this writing, there is a bug in the version of Foodcritic shipping with Chef Development Kit 0.2.0-2. It should check to see whether the metadata.rb file needs updating, as shown in Figure 16-15, but it doesn’t currently work with the cookbook output generated by
chef cookbook generate
.
We’re not sure if this rule will be fixed in future versions, if a new rule will be added to check for the Chef Development Kit version, or something else. So for now, if you are using the Chef Development Kit, change your metadata.rb file to match the Chef Client-generated version, as shown in Example 16-10.
After this change, the Chef Development Kit result should match the Chef Client version.
Chef Development Kit:
As shown in Figure 16-15, when Foodcritic detects an issue in your Chef code, you can look up more detail on the issue and how it can be fixed. In this case,
FC008
indicates that you should modify the metadata.rb file maintainer
and maintainer_email
fields to be something besides the default boilerplate text.
Let’s modify the metadata.rb file appropriately. Example 16-11 shows how we changed our file.
Run Foodcritic again. It should now report that
FC008
is no longer an issue:
Let’s create one more issue with our code. We’ll say that a Chef developer forgot to commit a README.md file into source control. Simulate this state by renaming the README.md file. Run the following
move
command:
Run Foodcritic as follows and you should see a new issue:
As you can see from the documentation on
FC11
, as shown in Figure 16-16, it is important to provide a README file in markdown format because Chef Supermarket expects your cookbooks to have documentation in a README.md file.
Ideally, you would fix this issue by writing some great documentation, but for now, just move the README.mdboilerplate back to its original name:
Run Foodcritic again, and it should report that
FC011
is no longer an issue:
Performing these Foodcritic checks should be a regular part of your Chef cookbook development cycle. TheFoodcritic documentation has more information on how to integrate Foodcritic with various build tools.
You can even use Foodcritic with many popular text editors, so it can perform Foodcritic runs while you type or when you save your Chef code.
You can create your own custom rules to extend the checks performed by Foodcritic. Etsy has published its set of custom Foodcritic rules online. You can use its custom rules as an example of how you can write rules more relevant to your environment.
Not all Foodcritic rules are trivial checks to see if you filled in the metadata.rb file or provided documentation. The Etsy custom Foodcritic rules, for example, check for issues that have caused outages in their production environment, such as
ETSY001
, as shown in Figure 16-17.
Foodcritic can be used to perform vital checks similar to
ETSY001
, to catch bugs in your code even before it gets deployed to a testing sandbox environment. A way to start might be to look through recent help desk incidents where you have identified the root cause being related to server configuration issues, and encode them as Foodcritic rules. This is the process Etsy used to develop its custom Foodcritic rule set.
We hope this section on Foodcritic shows you how you can catch bugs earlier in your Chef development process, closer to the time of coding. Catching issues early saves time and money.
Test Automation with ChefSpec
Another great tool that can help you run tests early in your development cycle is
ChefSpec
. You can even use it to catch errors before you code. ChefSpec can be used to produce runnable documentation. Its primary purpose is to help document and organize your code.
As a side benefit, ChefSpec tests and checks can uncover bugs when you make changes. Plus, your Chef code will be improved when it is guided by tests.
Similar to Serverspec, ChefSpec builds on RSpec. ChefSpec uses the RSpec description form to create runnable documentation. The form for ChefSpec documentation is slightly different from Serverspec’s, resembling the following:
For example, you would use the following
describe
block to contain examples performing tests against the apache-test::default
cookbook:
To perform an in-memory Chef run, you would add the following statements to the basic
describe
form, using classes and methods from the chefspec
gem. In this example, to test the apache-test::default
cookbook, you would use the following code:
ChefSpec uses an
expect
form similar to Serverspec’s. There are just different commands and matchers for ChefSpec. Following is a ChefSpec example that checks to make sure there is a reference in your Chef code to install the httpd
package:
Keep in mind that the preceding code is just runnable documentation. The
expect
statement does not perform an httpd
package installation during the in-memory Chef run. Instead, ChefSpec merely performs the in-memory Chef run to verify the cookbook syntax; in this case, to ensure that your code instructed Chef to install the package. This form of documentation-based testing is good enough for well-tested Chef primitives, such as the package
resource.
Commands in ChefSpec are usually the results of an in-memory Chef run. ChefSpec matchers are documented[ChefSpec matchers] are documented as shown in Figure 16-18.
If you expand the ChefSpec tree in the index on the left, you’ll see all the ChefSpec matchers listed, plus detailed examples, as shown in Figure 16-19.
WRITE YOUR FIRST CHEFSPEC TEST
The default location for ChefSpec tests are in a
spec
folder underneath your cookbook root. Make sure that the apache-test root cookbook directory is the current working directory, and create a spec directory as follows:
Create a file called default_spec.rb with the content shown in Example 16-12. Files containing ChefSpec code by convention are expected to end in the suffix *_spec.rb.
ChefSpec does not require any special
chefspec
command to run as it just extends RSpec. In the apache-testcookbook root, run rspec --color
as shown in the following example to perform a ChefSpec run:LAZY EVALUATION WITH LET
We need to introduce one more bit of RSpec syntax: lazy evaluation using the
let
helper method, which is part of the RSpec core. Figure 16-21 shows how ChefSpec commonly uses let
helper method to cache the results of the ChefSpec::Runner
object.
A call to the
ChefSpec::Runner
is fairly heavyweight. A call to let()
delays the evaluation of the ChefSpec::Runner
until when it is first used instead of when it is referenced in the source—thus the evaluation is “lazy.” Using let()
allows RSpec to cache the results of ChefSpec::Runner
when it is used multiple times in the same example.
Further, the
let()
call permits you to specify the recipe under test only once in your describe
block as documentation. Compare the following Without let and With let code examples, and notice that the call to ChefSpec::Runner
uses a described_recipe
macro to evaluate the recipe name instead of repeating the recipe string. A small optimization, but a useful one.
Without let:
With let:
When you rerun
rspec
, you should notice no net change in the test results:GENERATE A COVERAGE REPORT
Another ChefSpec helper method is
ChefSpec::Coverage.report!
. It will generate a list of resources that have corresponding examples as documentation. You can let this report guide your testing.
Edit default_spec.rb as shown in Example 16-14. The
at_exit
method is a part of core Ruby that permits you to register a block to execute when the program exits. In this case, we want to run the ChefSpec::Coverage.report!
method. The exclamation point (!) in the report!
method name is a Ruby convention that indicates a method is dangerous. In this case, the cautions are thatChefSpec::Coverage.report!
must be run after all tests are complete and not run more than once in a program. We use at_exit
to ensure that report!
is run once after the tests have finished.
Run
rspec --color
with the new at_exit
code, and notice that now a helpful report is generated, telling you the total number of resources in your code and how many have been tested in your specs:
Let this report guide you in choosing other tests to write for your code.
SHARE TEST CODE WITH SPEC_HELPER.RB
ChefSpec supports moving common code used in your tests to a spec_helper.rb file, similar to Serverspec.
As with Serverspec, you’ll have to imagine there are many test files in this example, and we’ll move the shared code to spec_helper.rb.
Create the file spec/spec_helper.rb with the content shown in Example 16-15. We are moving the
require
and at_exit
calls to this shared file.Summary
In this chapter we discussed how to test your Chef automation using Serverspec, Foodcritic, and ChefSpec. You need multiple tools because each is tailored to give you fast feedback at every stage of the Chef development lifecycle.
To learn more about test automation with Chef, check out the slides for the one-day course written by one of the authors of this book. This chapter was based on these slides.
Betway and Betway Casinos in Connecticut in 2021
ReplyDeleteBetway has 양산 출장샵 become the 안양 출장마사지 best 양산 출장마사지 betting site 강릉 출장마사지 in the 김포 출장샵 U.S. by offering an impressive array of casino games and poker games to its customers.