{"id":74,"date":"2019-06-17T19:21:23","date_gmt":"2019-06-17T19:21:23","guid":{"rendered":"https:\/\/www.bddtesting.com\/?page_id=74"},"modified":"2019-06-17T19:21:23","modified_gmt":"2019-06-17T19:21:23","slug":"the-need-for-behavior-driven-development-bdd-testing-tools","status":"publish","type":"page","link":"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/","title":{"rendered":"The Need for Behavior Driven Development (BDD) Testing Tools"},"content":{"rendered":"\n
\"\"\/<\/figure>\n\n\n\n

It should come as no surprise to learn that testing is at the heart of our engineers’ daily activities. Testing is intrinsic to our development process, both in practical terms and in our thinking. Our engineers work with complex systems that are made up of complex components. Individual components may have many external dependencies.<\/p>\n\n\n\n

When testing, the scope of what is to be tested is important \u2013 it can be system wide, focused on a particular feature or down deep into the methods and classes of the code. To be able to focus our testing, we want to be able to mimic or \u2018mock’ the behavior of external dependencies using a BDD testing tool.<\/p>\n\n\n\n

The purpose of this post is to walk through a couple of simple code examples and provide an overview of and explain the need for Behavior Driven Development (BDD) testing.<\/p>\n\n\n\n

BDD, Acceptance Tests, and Automation<\/h3>\n\n\n\n

At Rapid7 we apply the BDD methodology<\/a> which is an extension of Test Driven Development (TDD)<\/a>. BDD and TDD both advocate that tests should be written first, which for BDD this means acceptance tests (ATs), followed by unit tests driven by the ATs. For now, let’s say that at the outset of any task, BDD focus is on capturing the required behavior in User Stories, and from these acceptance tests (ATs) are written.<\/p>\n\n\n\n

Over time a large number of ATs are generated. Therefore not only is the methodology important but also the supporting tools to automate and manage our work. For some background on this, another colleague, Vincent Riou has described theautomated testing, continuous integration and code-quality control tools<\/a>that we use.<\/p>\n\n\n\n

BDD Testing Example: Ubiquitous Language and AT Scenarios<\/h3>\n\n\n\n

To borrow from Vincent’s post, \u201cThe idea with acceptance testing is to write tests (or behavioral specifications) that describe the behavior of your software in a language which is not code but is more precise than standard English.”<\/p>\n\n\n\n

Doing this allows people who are not software engineers, but have knowledge of the requirements, such as Product Management or Marketing, to write the scenarios that make up our ATs. This is a powerful thing when it comes to capturing the required behavior. People in the BDD community sometimes refer to this as a \u2018Ubiquitous Language’.<\/p>\n\n\n\n

Again borrowing from what Vincent states \u201cAdditionally, those tests can be run using a parser which will allow you to easily match your language to functions in the programming language of your choice.”<\/p>\n\n\n\n

Here is an example AT scenario \u2013 in this case following a template and language constructs used by the Cucumber \/ Gherkin parser.<\/a><\/p>\n\n\n\n

Given the customer has logged into<\/strong> their current account\nAnd the balance is<\/strong> shown to be 100 euros\nWhen the customer transfers 75 euros to their savings account\nThen the new<\/strong> current account balance should be 25 euros<\/pre>\n\n\n\n

Example step definition in Python<\/h3>\n\n\n\n

The following is an example of mapping a step definition to a Python function. In this case, the final step Then<\/em> is shown. This is where an \u2018assert’ is used to verify if the AT will pass or fail, depending on the final account balance.<\/p>\n\n\n\n

@Then('^the new current account balance should be \"([^\"]*)\" euros$')\ndef the_new_current_account_balance_should_be(self, expected_bal):\n  expected_bal = int(expected_bal)\n  assert expected_bal >= 0, \"Balance cannot be negative\"\n  new_bal = get_balance(account_id)\n  assert int(new_bal) == expected_bal, \"Expected to get %d euros. Instead got %d euros\" % (new_bal, expected_bal)<\/code><\/pre>\n\n\n\n

Since we are writing our tests before the actual implementation of the behavior, the AT will fail \u2013 so it’s important that the error message thrown by the \u2018assert’ is meaningful. Remember also that an AT may fail at a future date if some behavior of the \u2018system under test’ (SUT) is modified, intentionally or not \u2013 this is part of the value of having a body of automated ATs.<\/p>\n\n\n\n

Mocking Behavior of External Dependencies<\/h3>\n\n\n\n

The components and sub-systems that we work with have many external dependencies that can be complex. When running an AT against a particular component, it may be necessary to mock the external dependencies of that component. This is different from using a framework as described below in unit testing. Instead this is about trying to mimic the behavior of a second black-box so we can test the behavior of the first black-box.<\/p>\n\n\n\n

In our work we encounter this all the time, especially where a SUT has a dependency on the behavior of an external server. One approach for example is to build a simple mock server in Python using the Bottle module<\/a>, that gives us a basic server to build on. We mock the behavior that is required to meet the needs of the SUT. Note that this is not building a duplicate of an existing component \u2013 we are trying to mimic the behavior as seen by the SUT to complete our testing.<\/p>\n\n\n\n

BDD Testing Example: Unit Testing<\/h3>\n\n\n\n

After completing the acceptance tests come the unit tests. These are more closely coupled with the code of the final implementation, although at this stage we still do not start our implementation until the required unit tests are in place. This approach of acceptance tests and unit tests are applicable to GUIs.<\/p>\n\n\n\n

Unit Testing Example: Mocking with some JSON<\/h3>\n\n\n\n

The following example is a combination of using the Junit framework<\/a> with the Mockito library to create mock objects. In this example we want to show in a simple way a technique to mock a response that contains data in JSON format from a GET request on some external server. The test data, in JSON format, can be an actual sample captured in a live production scenario. We are also going to use a Google library to help with handling the JSON file.<\/p>\n\n\n\n

In this simple example we are testing a method \u2018getCountOfStudents’, found in a data access class, that is used by our imaginary application to get the number of students on a course using that course ID. The actual details for that course is held on some database externally \u2013 for the purposes of testing we don’t care about this database.<\/p>\n\n\n\n

What we are interested in, however, is that the method \u2018getCountOfStudents’ will have a dependency on another piece of code \u2013 it will call \u2018jsonGetCourseDetails’ which is found in an object called \u2018HttpClient’ \u2013 as the name implies this object is responsible for handling HTTP traffic to some external server \u2013 and it is from this server our application gets course data. For our test to work we therefore need to mimic the response from the server \u2013 which returns the data in JSON format \u2013 which means we want to mock the response of the \u2018jsonGetCourseDetails’.<\/p>\n\n\n\n

The following code snippets come from a Junit Test Class, that is testing the various methods found in the class that defines our data access object. Note the required imports for the Mockito and Google libraries are added.<\/p>\n\n\n\n

import static org.mockito.Matchers.any;\nimport static org.mockito.Matchers.eq;\nimport static org.mockito.Mockito.*;\nimport com.google.common.io.Resources;\nimport com.google.common.base.Charsets;<\/code><\/pre>\n\n\n\n

view raw<\/a><\/p>\n\n\n\n

Prior to running the test a mock object of the HttpClient is created using the test class \u2018setup()’ method, and tidied up afterwards with \u2018teardown()’.<\/p>\n\n\n\n

private HttpClient httpClient;\n@Before\npublic void setup() {\n  apiClient = mock(HttpClient.class);\n  ...\n  ...\n}\n@After\npublic void teardown() {\n  reset(httpClient);\n  ...\n  ...\n}<\/code><\/pre>\n\n\n\n

view raw<\/a><\/p>\n\n\n\n

For the test method itself, we use the Mockito when<\/em>, so when the \u2018jsonGetCourseDetails’ on the mock \u2018httpClient’ object is called with the \u2018course_id’, it then returns a mock response. We create the mock response using some test data, in JSON, we have in a file \u2018course_details.json’.<\/p>\n\n\n\n

@Test\npublic void testGetCountOfStudentsWithCourseID() throws IOException {\n  private String course_id = \"CS101\";\n  when(httpClient.jsonGetCourseDetails(eq(course_id))\n  .thenReturn(getMockResponse(\".\/tests\/course\/course_details.json\"));\n  Integer count = dao.getCountOfStudents(course_id);\n  Assert.assertEquals(10, count);\n}<\/code><\/pre>\n\n\n\n

view raw<\/a><\/p>\n\n\n\n

To create the mock response there is a utility method we have written that uses the Google library \u2018Resources’ class. For this example the method simply returns a mock response as the String from the \u2018Resources.toString’.<\/p>\n\n\n\n

private String getMockResponse(String jsonResource){\n  String MockResponse = null;\n  try {\n  MockResource = Resources.toString(Resources.getResource(jsonResource), Charsets.UTF_8);\n  }catch(IOException ex){\n  ex.printStackTrace();\n  }\n  return MockResponse;\n}<\/code><\/pre>\n\n\n\n

view raw<\/a><\/p>\n\n\n\n

At this stage we have a unit test with a mock object and we can use data in JSON format. Of course, also at this stage the test method will fail. Why? Because the implementation of the \u2018dao.getCountOfStudents(course_id)’ has not yet been done! We are writing our tests first, mocking the external dependencies (behavior) our code is reliant on.<\/p>\n\n\n\n

When writing the code for the implementation, we will know we are finished when all the tests are passing.<\/p>\n\n\n\n

https:\/\/blog.rapid7.com\/2017\/06\/19\/what-is-bdd-testing-practical-examples-of-behavior-driven-development-testing\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"

It should come as no surprise to learn that testing is at the heart of our engineers’ daily activities. Testing is intrinsic to our development process, both in practical terms and in our thinking. Our engineers work with complex systems that are ….  Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"pagelayer_contact_templates":[],"_pagelayer_content":"","_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"class_list":["post-74","page","type-page","status-publish","hentry"],"yoast_head":"\nThe Need for Behavior Driven Development (BDD) Testing Tools • BDD Testing<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"The Need for Behavior Driven Development (BDD) Testing Tools • BDD Testing\" \/>\n<meta property=\"og:description\" content=\"It should come as no surprise to learn that testing is at the heart of our engineers’ daily activities. Testing is intrinsic to our development process, both in practical terms and in our thinking. Our engineers work with complex systems that are ....  Read More\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/\" \/>\n<meta property=\"og:site_name\" content=\"BDD Testing\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.rapid7.com\/content\/images\/post-images\/63657\/practical-examples-of-behavior-driven-dev-testing.png#img-half-right\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/\",\"url\":\"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/\",\"name\":\"The Need for Behavior Driven Development (BDD) Testing Tools • BDD Testing\",\"isPartOf\":{\"@id\":\"https:\/\/www.bddtesting.com\/#website\"},\"datePublished\":\"2019-06-17T19:21:23+00:00\",\"dateModified\":\"2019-06-17T19:21:23+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.bddtesting.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"The Need for Behavior Driven Development (BDD) Testing Tools\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.bddtesting.com\/#website\",\"url\":\"https:\/\/www.bddtesting.com\/\",\"name\":\"BDD Testing\",\"description\":\"Behavior-driven development testing\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.bddtesting.com\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"The Need for Behavior Driven Development (BDD) Testing Tools • BDD Testing","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/","og_locale":"en_US","og_type":"article","og_title":"The Need for Behavior Driven Development (BDD) Testing Tools • BDD Testing","og_description":"It should come as no surprise to learn that testing is at the heart of our engineers’ daily activities. Testing is intrinsic to our development process, both in practical terms and in our thinking. Our engineers work with complex systems that are ....  Read More","og_url":"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/","og_site_name":"BDD Testing","og_image":[{"url":"https:\/\/blog.rapid7.com\/content\/images\/post-images\/63657\/practical-examples-of-behavior-driven-dev-testing.png#img-half-right"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/","url":"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/","name":"The Need for Behavior Driven Development (BDD) Testing Tools • BDD Testing","isPartOf":{"@id":"https:\/\/www.bddtesting.com\/#website"},"datePublished":"2019-06-17T19:21:23+00:00","dateModified":"2019-06-17T19:21:23+00:00","breadcrumb":{"@id":"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.bddtesting.com\/the-need-for-behavior-driven-development-bdd-testing-tools\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.bddtesting.com\/"},{"@type":"ListItem","position":2,"name":"The Need for Behavior Driven Development (BDD) Testing Tools"}]},{"@type":"WebSite","@id":"https:\/\/www.bddtesting.com\/#website","url":"https:\/\/www.bddtesting.com\/","name":"BDD Testing","description":"Behavior-driven development testing","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.bddtesting.com\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/www.bddtesting.com\/wp-json\/wp\/v2\/pages\/74"}],"collection":[{"href":"https:\/\/www.bddtesting.com\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.bddtesting.com\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.bddtesting.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bddtesting.com\/wp-json\/wp\/v2\/comments?post=74"}],"version-history":[{"count":1,"href":"https:\/\/www.bddtesting.com\/wp-json\/wp\/v2\/pages\/74\/revisions"}],"predecessor-version":[{"id":76,"href":"https:\/\/www.bddtesting.com\/wp-json\/wp\/v2\/pages\/74\/revisions\/76"}],"wp:attachment":[{"href":"https:\/\/www.bddtesting.com\/wp-json\/wp\/v2\/media?parent=74"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}