DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Driving DevOps With Smart, Scalable Testing
  • Unit Testing Large Codebases: Principles, Practices, and C++ Examples
  • Practical Use of Weak Symbols
  • Generate Unit Tests With AI Using Ollama and Spring Boot

Trending

  • Endpoint Security Controls: Designing a Secure Endpoint Architecture, Part 2
  • Agile and Quality Engineering: A Holistic Perspective
  • Mastering Advanced Traffic Management in Multi-Cloud Kubernetes: Scaling With Multiple Istio Ingress Gateways
  • Endpoint Security Controls: Designing a Secure Endpoint Architecture, Part 1
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. How Can You Use ChefSpec to Unit Test Chef Cookbooks?

How Can You Use ChefSpec to Unit Test Chef Cookbooks?

Learn how to set up a workstation to run Chef locally and use the existing Chef community cookbook to deploy the application on the local workstation environment.

By 
Greg Sypolt user avatar
Greg Sypolt
·
Nov. 30, 16 · Tutorial
Likes (0)
Comment
Save
Tweet
Share
5.9K Views

Join the DZone community and get the full member experience.

Join For Free

I recently had the opportunity to get involved with Chef cookbook development and begin learning how to write some tests for infrastructure code by using various testing frameworks. One critical aspect of developing any code is writing unit tests. We use ChefSpec, a unit testing framework for testing Chef cookbooks.

ChefSpec is simple to write. It reads a whole lot easier than other unit testing frameworks and provides fast feedback on cookbook changes without the need for a virtual machine or cloud machine.

Below, I'll show off ChefSpec in action by first setting up a workstation to run Chef locally, then using the existing Chef community cookbook to deploy the application on the local workstation environment. Finally, I'll walk through some of the units to make sure everything is working properly.

Workstation Prerequisite

To set up your local development environment, you'll first need to download the Chef Development Kit (DK). Why? I can specifically download Chef DK version 0.15.15 since I know it is compatible with my environment. The version will change as the Chef DK receives new updates (and it's your responsibility to validate the changes are compatible). Once you've downloaded and installed Chef DK, open up your terminal window and check the Chef version installed.

$ chef -v 
Chef Development Kit Version: 0.15.15
chef-client version: 12.11.18 
delivery version: 0.0.23
berks version: 4.3.5
kitchen version: 1.10.0 

Once you've downloaded and extracted the Chef Selenium community cookbook from the Chef Supermarket, open up your terminal window and navigate to the chef-selenium directory to finish preparing your local environment.

$ cd ~/work/chef-selenium
$ chef exec bundle install
...
...
Bundle complete! 10 Gemfile dependencies, 113 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.

Verify Chef Cookbook With Chefspec Tests (AKA Unit Testing)

ChefSpec allows us to simulate the convergence of resources to prove that the cookbook code works correctly before pushing changes to production. It's much easier and cheaper to catch bugs locally, as opposed to having a production application crash and burn. ChefSpec is the fastest way to test resources and recipes as part of a simulated chef-client on a local developer machine. It is an extension of RSpec, a behavior-driven development (BDD) framework that allows writing readable Ruby tests. Teams should aim for 100% coverage of code for unit testing. Every Chef cookbook should have a folder called “spec.” (This is where ChefSpec unit tests live.) Let's review the chef-selenium file structure for unit testing:

|- chef-selenium/
|-- recipes/
|---- default.rb
|---- hub.rb
|---- node.rb
|-- ... |-- spec/
|---- unit/
|------ default_spec.rb
|------ hub_spec.rb
|------ node_spec.rb
|---- spec_helper.rb

When writing unit tests for your cookbook, the standard is to create a separate spec test for each recipe in the /spec folder.

We're only reviewing the spec test default_spec.rb that describes the default.rb recipe. This recipe downloads and installs the Selenium Standalone JAR file for Windows, Linux, and Mac OS. The SoloRunner allows us to simulate testing against the different operating systems (platforms) and versions by passing a parameter. Lines 6, 46, and 87 simulate the Chef run-in memory, as previously described, and override any defined node attributes that we'll use in our spec tests later.

6 ChefSpec::SoloRunner.new(platform: 'windows', version: '2008R2' do |node|
...
...
46 ChefSpec::SoloRunner.new(platform: 'centos', version: '7.0' do |node|
...
87 ChefSpec::SoloRunner.new(platform: 'mac_os_x', version: '10.10') do |node|

source: https://github.com/dhoer/chef-selenium/spec/unit/default_spec.rb (Lines 6, 46, and 87)

Let's look at the different ways to test whether a package resource is installed or not installed with ChefSpec. Line 1 tells Chef to unzip the package unless the platform is Windows or Mac OS.

1 package 'unzip' unless platform?('windows', 'mac_os_x')

Source

For the next test, Line 6 tells Chef to simulate a test run against Windows 2008R2 by calling the default recipe to determine if the package will be unzipped. In Line 14, by using ChefSpec PackageMatcher, you can validate that a package was not installed for the Windows platform.

Windows

6 ChefSpec::SoloRunner.new(platform: 'windows', version: '2008R2' do |node|
...
13 it 'does not install zip package' do
14    expect(chef_run).to_not install_package('unzip')
15 end

Source

Next test: Line 57 proves that a package was installed for the Linux platform.

Linux

46 ChefSpec::SoloRunner.new(platform: 'centos', version: '7.0' do |node|
...
56 it 'installs package' do
57 expect(chef_run).to install_package('unzip')
58 end

Source

Next test: Line 7 sets the environment variable SYSTEMDRIVE for Windows, and Lines 8-9 “override” a node attribute [‘selenium’] [‘url’] that we’ll use in our specs later. Line 34 simulates the download of the Selenium Standalone JAR file by using the ChefSpec RemoteFileMatcher to verify the remote file was created.

7 ENV['SYSTEMDRIVE'] = 'C:'
8 node.override['selenium']['url'] =
9 'https://selenium-release.storage.googleapis.com/2.48/selenium-server-standalone-2.48.0.jar'
...
...
33 it 'downloads jar' do
34 expect(chef_run).to create_remote_file('C:/selenium/server/selenium-server-standalone-2.45.0.jar')
35 end

Source

To run ChefSpec, from the terminal, go to the root of your cookbook chef-selenium and run Rake. As you can see by reviewing the console output, the chef-selenium cookbook does not have 100% test coverage, but all ChefSpec tests passed.

Terminal Console Output

$ chef exec bundle exec rake
Finished in 23.33 seconds (files took 2.27 seconds to load)
52 examples, 0 failures

ChefSpec Coverage report generated... 

   Total Resources: 36
   Touched Resources: 35
   Touch Coverage: 97.22%

Untouched Resources:

   remote_file[/opt/selenium/server/selenium-server-standalone-3.0.0.jar] selenium/recipes/default.rb:16

The test coverage output is disabled as the default setting. The following code snippet needs to be inside the spec/spec_helper.rb file to enable test coverage. I recommend enabling test coverage for any application code.

Enable ChefSpec Test Coverage

ChefSpec::Coverage.start!

Source

Conclusion

In this post, we set up a clean development environment and reviewed some of the ChefSpec tests for the chef-selenium default recipe, executed them across multiple platforms, and analyzed the test coverage output. Your infrastructure code deserves testing, and before deploying those servers, prove that your cookbook works.

This blog post only scratches the surface of testing Chef cookbooks. Just taking the time to learn something new can be a daunting task. There are a lot of new concepts to learn and best practices to understand when developing and testing infrastructure code. To continue learning about ChefSpec and RSpec testing extensions, you can reference these documentation links to test cookbooks, recipes, and resources:

  • Learn Chef
  • RSpec Expectations
  • ChefSpec
unit test Chef (software)

Published at DZone with permission of , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Driving DevOps With Smart, Scalable Testing
  • Unit Testing Large Codebases: Principles, Practices, and C++ Examples
  • Practical Use of Weak Symbols
  • Generate Unit Tests With AI Using Ollama and Spring Boot

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: