# Test Driven Development with Ansible?

**URL:** <https://forum.ansible.com/t/test-driven-development-with-ansible/14128>\
**Category:** Ansible Project\
**Created:** [December 11, 2013, 4:39pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128 "2013-12-11T16:39:33Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Aaron\_Hunter](https://avatars.discourse-cdn.com/v4/letter/a/e19adc/32.png) [@Aaron\_Hunter](https://forum.ansible.com/u/Aaron_Hunter)\
**Post date:** [December 11, 2013, 4:39pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/1 "2013-12-11T16:39:33Z")

</div>

I come from an Agile software development background in which test driven development (TDD) is the norm. As I write Ansible scripts, I’d like some way of testing them. In principle, I want to test every command in a playbook. For example, if one of my command changes the user permissions on a file, I want a test that independently confirms that it has in fact done so. I don’t see a “test” module but I may have missed it.

Is that something that Ansible may offer some day? I’m thinking of the Ansible equivalent to unit testing. I believe it would require the ability to execute arbitrary Python code in the test. The Java tests I have written could certainly be very complex.

I’m also curious what others do for testing using Ansible. What frameworks, etc.

Thanks,  
Aaron  
DevOps Blog: [http://www.sharknet.us](http://www.sharknet.us)

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [December 11, 2013, 4:55pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/2 "2013-12-11T16:55:40Z")

</div>

Yes, this is super easy to already do today, basically just call your tests at the end as the last step of your playbook.

Executing arbitrary python code is possible, but you can use ansible modules like get\_url and fail and so on.

If you want to push a python script, the ‘script’ module is awesome for that.

Many of users have tests integrated with their continuous deployment process so it will fail the rolling update block before moving on the to next, thus not taking more machines out of rotation.

However, if you feel you have to test the file module, seriously, you’re wasting time – if the file module doesn’t work for you, how good is the product? It would be much better to test instead for something functional, like whether your web service is operational, rather than duplicating all the basics of Ansible in, as you say, arbitrary python code just to make sure Ansible works.

There’s a difference between unit and integration testing, and also in testing a live deployment.

Unit tests are things you run on development code.

---

<div class="post-metadata">

**Author:** ![Aaron\_Hunter](https://avatars.discourse-cdn.com/v4/letter/a/e19adc/32.png) [@Aaron\_Hunter](https://forum.ansible.com/u/Aaron_Hunter)\
**Post date:** [December 11, 2013, 5:54pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/3 "2013-12-11T17:54:34Z")

</div>

I see your point but I’m not sure I agree. “Unit testing” may not be the best term for it but it’s not too far off. Consider this case instead: installing and configuring a DHCP server. I have my senior admin write down exactly what the DHCP deployment should look like. This is how success will be measured. Testing this will include checking file permissions (which is also security issue), processes are running and with the right settings, logging , and a whole set of functionality based on the config file of the DHCP server.

Another admin (let’s say a junior admin) writes the Ansible code to accomplish this. When the code passes the test, it is done. Certainly this crosses into what is traditionally called functional testing. Testing IT infrastructure is somewhat different from testing a new software development. I would still test what is in the Ansible script for the DHCP server because the junior admin may have gotten it wrong and plus its still code and you always test code. Plus I would have the Ansible scripts initially written in a development environment with one suite of tests. These tests will be very obtrusive and are not the same I would use to test a successful deployment.

To be sure, the most important part is testing that the DHCP server works as expected (i.e., testing the config file) which is not an Ansible issue. Still I would test everything. The issue for me is what to use to write the tests? Cucumber? JBehave? Plain Python? I know plenty of tools designed to test custom apps/code, I don’t think the IT testing tools have caught up yet.

Maybe this isn’t even an Ansible issue. I was just speculating on how it might include automated TDD-like test process in the framework.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [December 11, 2013, 5:57pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/4 "2013-12-11T17:57:34Z")

</div>

My point is if Ansible’s file module at that level must be verified you have greater problems 🙂

Definitely you can invoke tests of any kind from playbooks, script module, get\_uri, fail module with when, stat module, etc, etc – or call another test system, locally or remotely

– Michael

---

<div class="post-metadata">

**Author:** ![John\_Dewey](https://avatars.discourse-cdn.com/v4/letter/j/b9bd4f/32.png) [@John\_Dewey](https://forum.ansible.com/u/John_Dewey)\
**Post date:** [December 11, 2013, 6:00pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/5 "2013-12-11T18:00:19Z")

</div>

Hi Aaron -

I too would find it useful to have the ability to “unit test” my tasks. However, I have opted to create a testing playbook [1] which handles integration testing. It is not perfect, but allows for TDD/BDD, and integrate into CI gating.

[1] [https://github.com/blueboxgroup/ursula/tree/master/playbooks/tests/tasks](https://github.com/blueboxgroup/ursula/tree/master/playbooks/tests/tasks)

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [December 11, 2013, 6:05pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/6 "2013-12-11T18:05:00Z")

</div>

If the model is declaring desired state you test the outcome, not the implementation

Can I ping X, is this route able, is this web service up – not does this file look like this.

Think at the higher level and write tests that matter that are not just basic asserts.

– Michael

---

<div class="post-metadata">

**Author:** ![Takatsugu\_Shigeta](https://avatars.discourse-cdn.com/v4/letter/t/ea5d25/32.png) [@Takatsugu\_Shigeta](https://forum.ansible.com/u/Takatsugu_Shigeta)\
**Post date:** [December 11, 2013, 6:13pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/7 "2013-12-11T18:13:29Z")

</div>

If you are familiar with RSpec (in Ruby), I recommend serverspec [1] for testing as BDD style.

[1] [http://serverspec.org](http://serverspec.org)

– shigeta

---

<div class="post-metadata">

**Author:** ![Brian\_Coca1](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@Brian\_Coca1](https://forum.ansible.com/u/Brian_Coca1)\
**Post date:** [December 11, 2013, 7:39pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/8 "2013-12-11T19:39:34Z")

</div>

FYI, there are quite a few unit test already that verify that ‘the file module’ works as advertised, you can run ‘make tests’ in an ansible checkout to get them. There should be no need to do this per playbook.

not all modules or cases are covered but if you want to add tests at this level I suggest looking into the ‘test’ dir in the ansible checkout.

Do you tests all core java libraries when you deploy a war to tomcat?

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [December 11, 2013, 7:45pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/9 "2013-12-11T19:45:05Z")

</div>

Well phrased Brian, that was my point which I was having trouble trying to share.

The name “unit testing” versus “integration testing” (especially what happens in stage environments) or “monitoring” is vitally important.

You can trust that the “file” module works, so it’s great if you test whether the application is operational at the end and things like that.

We also have some integration tests for ansible modules that are going to be rolled into our buildsystem and project soon that are more intrusive than our core unit tests.

But what you want in production to make sure you have an app running before moving to the next rolling update slice is not a unit test, but something higher level

Ansible makes this easy by following a “fail first” mode, if something happens along the way, you don’t end up with a system that is only 45% configured and then returned  
success because it evaluated part of the DAG – it makes you fix all your problems, and this makes it very very stable in a rolling update process.

The modules are all coded to fail when they hit error conditions.

---

<div class="post-metadata">

**Author:** ![Aaron\_Hunter](https://avatars.discourse-cdn.com/v4/letter/a/e19adc/32.png) [@Aaron\_Hunter](https://forum.ansible.com/u/Aaron_Hunter)\
**Post date:** [December 11, 2013, 8:30pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/10 "2013-12-11T20:30:31Z")

</div>

I should clarify a bit because it looks like I have given you the wrong impression. I have confidence that the Ansible modules behave as advertised. My experience with them to date has been excellent. The Ansible code is not what I’m trying to test.

What I want to test is that the _administrator_ has used Ansible to configure a system in a way that meets the spec. In other words, I want to test that the admin has written a _correct_ Ansible script. Writing an Ansible playbook is like writing code. When you write code you have to test it externally. I intend exactly what Michael wrote above: testing outcome not implementation. If I don’t test the results of the playbook, how do I know the admin wrote the correct script?

–Aaron

---

<div class="post-metadata">

**Author:** ![Patrick\_Regan](https://avatars.discourse-cdn.com/v4/letter/p/7cd45c/32.png) [@Patrick\_Regan](https://forum.ansible.com/u/Patrick_Regan)\
**Post date:** [December 11, 2013, 8:39pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/11 "2013-12-11T20:39:08Z")

</div>

I guess my trouble of understanding is how would this test be different than just the play itself. I’m not exactly an expert so forgive me, but given that plays are written in a declarative “This is what I want” style, wouldn’t the tests essentially be saying exactly the same?

In other words why have more granularity than “start apache; test port 80” which can be done with existing modules? Or am I missing this whole conversation altogether?

---

<div class="post-metadata">

**Author:** ![Aaron\_Hunter](https://avatars.discourse-cdn.com/v4/letter/a/e19adc/32.png) [@Aaron\_Hunter](https://forum.ansible.com/u/Aaron_Hunter)\
**Post date:** [December 11, 2013, 8:43pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/12 "2013-12-11T20:43:32Z")

</div>

John,

That is pretty good. I like the method you use to do the tests and t that you put them in a separate playbook. Following TDD style, the test playbook could be written first, then the implementing playbook. When you check in the implementing playbook in version control, the CI server can run the tests. Nice. I’ll give this a try.

–Aaron

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [December 11, 2013, 8:45pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/13 "2013-12-11T20:45:56Z")

</div>

Exactly, Ansible playbooks are declarative.

I would disagree that it’s like writing code for the most part, it was designed to be very far from that, but there are definitely steps involved that happen in order.

You are meant to read the playbook and we made them very auditable for this reason.

Of course, monitoring is a very very good idea.

An example of this is what if a playbook does something you don’t have a test for, but you still don’t want… you can only get that by reading the playbook, which is why it’s designed to be so easy to read and follow changes in source control diffs.

I don’t think you need to write a test to say “foo is installed” as the Ansible module enforces that.

You do want to test that your web service is running ok, and not just at deploy time, but also in your monitoring.

---

<div class="post-metadata">

**Author:** ![Brian\_Coca1](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@Brian\_Coca1](https://forum.ansible.com/u/Brian_Coca1)\
**Post date:** [December 11, 2013, 9:07pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/14 "2013-12-11T21:07:00Z")

</div>

wouldn’t a test playbook match the ‘production’ one?

---

<div class="post-metadata">

**Author:** ![Stephan\_Buys](https://avatars.discourse-cdn.com/v4/letter/s/f08c70/32.png) [@Stephan\_Buys](https://forum.ansible.com/u/Stephan_Buys)\
**Post date:** [December 12, 2013, 7:34am UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/15 "2013-12-12T07:34:53Z")

</div>

Hi Aaron,

Please find attached a small (and definitely imperfect/ugly/hacky) callback plugin that I wrote for ansible, It produces xUnit output from ansible playbook runs and integrates very nicely into Jenkins (xUnit → Check Version N/A [http://check.sourceforge.net](http://check.sourceforge.net))

It should be copied to {{ ansible\_dir }}/ansible/lib/ansible/callback\_plugins/

I use it for TDD of my own infrastructure/code and use it in a pattern very similar to what John linked to below. Complex tests are implemented as scripts (rolename/files), and “test suites” are bundled into roles (roles/test\_server\_live, roles/test\_server\_logon, etc).

I’ve found that it works really well when integrating it into my build processes on Jenkins to catch errors and test for expected behaviour at an infrastructure/functional level. Of course it is up to you to creatively use ansible to do the tests. I use a combination of modules and scripts wrapping 3rd party tools, and rely on the return code to trigger “success” and “failure” in ansible.

Another note, I have ignore\_errors peppered throughout the playbooks so that all relevant tests can run, ansible’s conditionals, etc make this a very powerful setup, here is a short example:

- name: Check vagrant user logon (should fail)  
local\_action: shell roles/test\_auth\_local/files/check\_vv.sh  
ignore\_errors: yes

I hope that this is a step in the right direction, with any luck someone can polish the plugin and integrate it into the ansible codebase. Otherwise if there is interest, please indicate as much and I’ll try to get it into github for a proper pull request or to maintain it separately.

Kind regards,  
Stephan

> **(attachments)**
>
> [xunit.py](https://forum.ansible.com/uploads/short-url/4tqF7o3zb6fMhJP6g4kW2kq5zyV.py) (8.88 KB)

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [December 13, 2013, 4:11pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/16 "2013-12-13T16:11:37Z")

</div>

Hey guys, quick note – if you are sharing something, link to github, please don’t attach files to the mailing list. (I really need to turn this off).

Also makes it easier to browse and look around, etc 🙂

---

<div class="post-metadata">

**Author:** ![\_volanja](https://avatars.discourse-cdn.com/v4/letter/_/958977/32.png) [@\_volanja](https://forum.ansible.com/u/_volanja)\
**Post date:** [December 17, 2013, 5:03pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/17 "2013-12-17T17:03:01Z")

</div>

Hi Aaron and All

I use Severspec(introduced by shigeta) for TDD.  
Now, Ansible has unit-test. but, as you say, I can not verify that the servers are configured correctly.(e.g. setup DHCP)  
ServerSpec can verify that the servers are configured correctly!!  
It’s popular software in Japan:)

ServerSpec says.  
Serverspec tests your servers’ actual state through SSH access, so you don’t need to install any agent softwares on your servers and can use any configuration management tools, Puppet, Chef, CFEngine and so on.

So, I create sample (install Nginx,open port 80, and Test!) at Github. Please check & try.  
[https://github.com/volanja/ansible-sample-tdd](https://github.com/volanja/ansible-sample-tdd)

Thanks!  
– volanja  
[volaaanja@gmail.com](mailto:volaaanja@gmail.com)  
[https://twitter.com/volanja](https://twitter.com/volanja)

2013年12月12日木曜日 1時39分33秒 UTC+9 Aaron Hunter:

---

<div class="post-metadata">

**Author:** ![Jesse\_Keating](https://avatars.discourse-cdn.com/v4/letter/j/3bc359/32.png) [@Jesse\_Keating](https://forum.ansible.com/u/Jesse_Keating)\
**Post date:** [December 17, 2013, 6:57pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/18 "2013-12-17T18:57:45Z")

</div>

So this is testing the product itself. That's cool and interesting, but what I'm really interested in is testing of my playbook changes themselves. Something I can run as a gate check on changes coming into my playbook repository. Syntax checking, referencing the right external files, etc...

-jlk

---

<div class="post-metadata">

**Author:** ![Aaron\_Hunter](https://avatars.discourse-cdn.com/v4/letter/a/e19adc/32.png) [@Aaron\_Hunter](https://forum.ansible.com/u/Aaron_Hunter)\
**Post date:** [December 28, 2013, 12:59pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/19 "2013-12-28T12:59:37Z")

</div>

volanja,

Thanks for the link. serverspec looks like a good option since it has a nice syntax and already has several suitable modules. I’d like to see an Ansible module that could run these tests. Maybe have a ‘spec’ directory under each role and be able to call them from the role’s playbook. This would add a TDD capability to Ansible.

To those who are not convinced testing is needed in this case I would just add that testing is always needed. Whenever you change a table constraint in your databases you test it, when you change the VLAN config in your switch you test it, when you write a new function in your program you test it, when you change your DHCP config you test it. If you care about quality the issue is not whether to test, it is only how to test. The Agile, DevOps approach is to automate everywhere hence the need for automated CM tests like serverspec.

–Aaron  
Blog: [http://www.sharknet.us](http://www.sharknet.us)

---

<div class="post-metadata">

**Author:** ![Patrick\_Regan](https://avatars.discourse-cdn.com/v4/letter/p/7cd45c/32.png) [@Patrick\_Regan](https://forum.ansible.com/u/Patrick_Regan)\
**Post date:** [December 30, 2013, 8:09pm UTC](https://forum.ansible.com/t/test-driven-development-with-ansible/14128/20 "2013-12-30T20:09:54Z")

</div>

So I’m not a super expert on this or anything, but I think I’m going to disagree with you here. To illustrate my point I’m going to use the example from Serverspec.

```auto
describe package('httpd') do
  it { should be_installed }
end

```

This is accomplished by the `yum` module. It will report changed, OK, or Failed.

```auto
describe service('httpd') do
  it { should be_enabled }
  it { should be_running }
end

```

`service` module…

```auto
describe port(80) do
  it { should be_listening }
end

```

Pretty much anything in the [Network](http://www.ansibleworks.com/docs/modules.html#network) category of modules would work. Or doing a `local-action` port connection with `register`

```auto
describe file('/etc/httpd/conf/httpd.conf') do
  it { should be_file }
  it { should contain "ServerName [www.example.jp](http://www.example.jp)" }
end

```

`Stat`/`File`/`lineinfile`.
