Talks

TDDing tmux

by Seth Vargo

The video titled "TDDing tmux" features Seth Vargo discussing the process of implementing test-driven development (TDD) within Chef cookbooks, emphasizing its accessibility to both developers and operations teams. Seth, a Solutions Engineer at Ops Code, begins by engaging the audience in a discussion about their backgrounds as Rubyists and operations personnel, pointing out the disparity in testing practices between the two groups.

Key points discussed in the presentation include:
- Introduction to Testing in Chef: Seth highlights the importance of applying familiar Ruby testing techniques in the context of Chef, which operates using Ruby. He underscores the usefulness of TDD and encourages collaboration between Ruby developers and operations personnel.
- Essential Tools: He introduces several critical tools for testing Chef cookbooks:

- ChefSpec: A testing framework that simulates Chef in memory, allowing users to verify that code behaves as expected.

- Fauxhai: A tool developed to simulate different operating system environments, providing the necessary node attributes that ChefSpec requires.

- Foodcritic: A linting tool that helps ensure adherence to best practices while writing Chef cookbooks.

- Strainer: A Ruby gem designed to define and execute tests efficiently across a code base, especially useful for CI/CD pipelines.

- Guard: A command-line tool that watches for file changes and runs defined tests automatically.

- Creating a Cookbook: Seth walks through the process of creating a new cookbook for tmux, using the Knife CLI. He explains the importance of editing the metadata and writing specs for TDD.

- TDD Process: The video details the cycle of writing tests, understanding failures, and developing code until the tests pass, promoting a disciplined development process.

- Running Tests and Linting: Seth emphasizes running Foodcritic for linting and validating cookbook practices, alongside Knife for Ruby syntax checking. He discusses the integration of Strainer into CI systems to streamline testing.

The comprehensive overview concludes with an invitation for questions, reiterating the importance of TDD in ensuring quality and collaboration in Chef development processes. He encourages the audience to leverage these tools for more effective cookbook management and testing.

00:00:14.920 Hello everyone, I’m Seth Vargo. I’ll do a little introduction. Welcome to TDDing tmux! It has a cool name, right? It’s fun to say, and everyone loves alliteration.
00:00:28.240 So how many people here consider themselves Rubyists or developers? By a show of hands. Great! A little over half. Now, how many people consider themselves operations folks or ops people? Cool. How many of those Rubyists test their code every day or every time they do something? That’s impressive, about 99.99%.
00:00:39.360 Now, how many operations people test their code? That’s like three. Cool! The whole point of this talk is about that. You should make friends with those Rubyists because everything I’m going to tell you today is what they’re already doing for their existing code. If you need help making friends, there’s a really good article on WikiHow.
00:01:07.280 So, what is this talk really about? I couldn’t fit everything on the slide, but it’s about how to apply the testing techniques you already know in Ruby to Chef, because Chef is just Ruby. And by the way, I'm Seth Vargo. You might recognize me by my familiar red-faced avatar.
00:01:28.080 I now work for Ops Code, so I have this beautiful black-and-white Ops Code avatar. As I mentioned, I’m a Solutions Engineer at Ops Code, I lead our Learn Chef campaign, and I also hold all our office hours for newbies. So if you want help with Chef, feel free to come and talk to me.
00:01:46.640 And a shameless plug: we’re hiring! If you’re interested in anything, head to opscode.com/careers. Let’s talk about testing because that’s what you came here to discuss. As with any great project, it all starts on GitHub.
00:02:02.399 We’re going to look at the Ops Code Chef repository, which is available at github.com/opscode/chef-repo. It looks like this: it’s your standard Chef repo. If you’ve ever looked at a Chef repo, you’ll see a bunch of very common files and folders, and Josh writes all of them. We’re going to clone this to our local machine.
00:02:30.000 I was going to live code this, but as you all are aware, the Wi-Fi is a bit spectacular, and I have to download gems, so this is now a slide deck. Sorry, Sasha! The first thing we need to do is create a Gemfile.
00:02:43.440 If you aren’t familiar with Gemfiles, this is just Bundler’s way of managing dependencies. We’re going to add a few things. First, we’re going to add Chef, which is all about infrastructure as code automation. I get paid to say that! You can use Ruby code to configure your servers; you can manage one server or a bazillion servers. It’s pretty awesome, and you should use it.
00:03:07.760 Now, ChefSpec, as you may have guessed—especially for the Ruby developers—is our testing framework for your Chef cookbooks. It uses the same syntax that you’re already accustomed to, but it actually runs Chef in memory and reports on the results. In reality, it’s like a major hack; it injects itself into all of your resources and ensures that they ran. It’s really cool because it works.
00:03:43.520 Next up is Fauxhai. ChefSpec lacked a critical component, which was node attributes. Under the hood, Chef uses Ohai, which is an awesome tool that outputs your provisioned system as JSON data. You can use that, which contains everything from your users to your IP address and pretty much everything you’d want to know about your system. You can use that as a third-party tool outside of Chef.
00:04:38.320 The trouble is, ChefSpec expects certain attributes to be defined, particularly node-specific attributes that are specific to systems like Ubuntu versus CentOS. There’s no easy way to do that unless you want to type out 300 lines of JSON in every test, and nobody wants to do that. So, I wrote Fauxhai back when I was an intern at Custom Inc. My view was to open-source this system data.
00:04:49.440 Fauxhai took off, and we can simulate different operating systems for testing. You can pretend to be a Windows machine on your OSX box or an Ubuntu instance with multiple versions on your CentOS box, which is especially handy for testing because if you're unit testing against an Ubuntu instance and your cookbook behaves differently than it does on a CentOS instance, you need to test that without needing multiple laptops.
00:05:00.880 Another tool we’ll talk about is Foodcritic. How many people are familiar with tools like JSLint or similar? Foodcritic serves that purpose for Chef cookbooks. It’s nothing more than a linting tool and is an ever-growing project. Andrew Crump just released a new version, so there are all kinds of rules available.
00:05:26.160 It helps catch common pitfalls and mistakes by following the simple rules it provides. Next, I'll talk about a tool called Strainer in more detail. It’s a sandboxing isolation tool that allows you to move a cookbook into an isolated environment and run tests against it to see how it behaves independently, which is important in unit testing as you don’t want third-party factors affecting your tests.
00:05:54.639 Finally, we’ll talk about Guard. A lot of Rubyists are probably familiar with Guard. It’s essentially a command-line tool that watches the file system for modification events. Anytime you save or update a file, you can configure Guard to trigger actions; you define the triggers based on regular expressions.
00:06:18.400 Let’s get started with creating a cookbook. This is TDDing tmux, and we'll focus on tmux. How many people here don’t know what tmux is? It’s a terminal multiplexer. It’s cool and allows multiple users to code in the same remote session.
00:07:38.320 Now, the first thing we need to do is create a blank cookbook using Knife, which is the CLI for Chef. We’ll issue a command: knife cookbook create <cookbook_name> with the name being tmux. This is similar to commands in Rails or Ruby.
00:08:15.040 It creates a scaffold for us and shows output indicating which files were created. If we look at those files in our editor, we’ll see there are several folders and files like attributes, recipes, and templates. This is standard output, but we don’t really need half of these, so we’ll remove them to simplify things. We'll mainly focus on attributes, recipes, and templates.
00:09:14.560 The first thing we want to inspect is the metadata. Anytime you create a new cookbook, this should be the first thing you edit, just like you edit your gemspec for new gems. Update the version number and add a description if you’d like. Because we’re doing test-driven development, we will write specs.
00:10:00.600 Now that we have our cookbook scaffolded, we only did this because our specs will live within our cookbook. Everything we do moving forward will be based on test-driven development—writing specs, watching them fail, then writing code and watching them pass.
00:10:45.760 The first thing we'll create is a spec helper at the root of our Chef repo, requiring ChefSpec. You might ask why not just require ChefSpec at the top of every file. The spec helper is a common practice for sharing spec configuration across the project, enabling shared variables and configurations to be centralized.
00:11:40.480 Using the spec helper allows us to keep our tests organized and makes them more accessible. While some people consider this an anti-pattern, it’s a helpful practice for many.
00:12:03.040 Now let's create the default specs, which will live in the spec directory. It’s common practice to name the spec corresponding with the recipe, so for the default recipe, we’ll name it default_spec.rb.
00:12:35.600 Let’s write our first test! We need to create a Chef runner. There are various ways to define variables; I prefer using `let` because it’s lazy-loaded in RSpec.
00:13:34.720 This is the syntax for creating a new Chef runner. We converge on the tmux cookbook, specifying the default recipe. You can leave out the default, but clarity is important.
00:14:14.560 Next, we assign our runner object and write the first test. Simple RSpec syntax—expect the runner to install the tmux package. This is straightforward and understandable for both technical and non-technical individuals.
00:15:26.880 Next, we’ll create our configuration file to manage keyboard shortcuts and bindings, which is a key feature of tmux. You might be wondering where the install package function and runner come from; they come from the extensive GitHub documentation for ChefSpec, which you should avoid reading all at once!
00:16:40.640 In our tests, we need to ensure that the template we defined exists. If it doesn't, we update our specs to include a check for that. Super powerful and essential for testing templates with dynamic variables.
00:17:57.760 Once we create the tmux.conf file and save it, all tests should pass. This is how you conduct test-driven development effectively.
00:18:31.200 Next, we need to conduct linting tests using Foodcritic, a vital tool for ensuring code quality when contributing to shared cookbooks. Run Foodcritic to check for adherence to best practices.
00:19:40.080 Foodcritic provides feedback, and you should take that seriously, especially when working with teammates or the wider community.
00:20:12.080 The next step involves using Knife cookbook test, which will not only validate Ruby syntax but also ensure all referenced files and templates exist.
00:20:56.320 It's crucial to run this test as it can catch errors ChefSpec might miss. Now, managing multiple commands in your CI/CD pipeline can be cumbersome, which is why we could streamline this process.
00:21:28.560 To facilitate this, I developed Strainer, a Ruby gem that helps define and execute tests quickly across your code base. This is particularly useful for teams managing several cookbooks simultaneously.
00:22:02.160 You can utilize Strainer in CI systems like Jenkins or CircleCI, integrating it seamlessly into your workflow.
00:22:41.440 In summary, by utilizing these tools and practices, you can ensure your Chef development process is efficient, effective, and collaborative. Now, if you have any questions, feel free to ask now or reach out to me via email.
00:23:25.760 Thank you for your attention and I hope you found this presentation helpful.