An introductory tutorial on behavior-driven development in Python _python

Source: Internet
Author: User
Tags documentation readable

For drive development (Behavior-driven DEVELOPMENT,BDD) is an excellent development model. can help developers develop a good habit of day-to-day knot, so as to avoid or even eliminate the "last minute" situation, so it is helpful to improve the quality of the code. The test structure and design form combined with Gherkin grammar make it very readable for all the members of the team, including the non-technical.

All code has to be tested, which means that the system's flaws are minimized or even zero when it comes online. This needs to match the complete test suite, from the overall control of the software behavior, so that detection and maintenance can be in order. This is the charm of BDD, don't you?

What is BDD?

The concept and theory of BDD is derived from TDD (test-driven development), and the theoretical point of TDD is to write tests before coding. The difference is in addition to the use of unit testing for fine-grained testing, but also using the acceptance test (acceptance tests) throughout the program. Next we will combine the lettuce test framework to explain.

The BDD process can be simply summed up as:

    • Write a flaw Acceptance test
    • Write a defect unit test
    • Make unit tests Pass
    • Refactoring
    • Make the acceptance test pass

In each feature, repeat these steps if necessary.

BDD in Agile development

In agile development, BDD is a duck in the box.

If the new features and requirements of the project are changed every two weeks, the team needs to work with fast paced testing and coding. Acceptance and unit testing in Python can help you achieve that goal.

The test is well known for the use of an English-formatted "feature" description file containing tests and individual tests. The advantage of this is that the entire project team is involved, in addition to the developers, as well as managers and business analysts who are not involved in the actual testing process of the non-technical members.

The writing of feature files follows the rules of all readable, so that both technical and non technical members can understand and receive clearly. If you include only unit tests, it is possible to cause a requirement analysis to be incomplete or impossible to agree upon. The biggest advantage of being tested is its applicability, regardless of the size of the project can be freely.

Gherkin syntax

Gherkin is usually used to write acceptance tests, gherkin from the cucumber Framework, written by the Ruby language. The Gherkin syntax is very simple, and the following 8 points are used primarily in lettuce Python to define features and tests:

    • Given hypothesis
    • When time
    • Then next
    • And AND and
    • Feature Features:
    • Background background:
    • Scenario Outline Occasion Outline:


Use Python's commonly used PIP install statements to complete the installation of lettuce packages:

$ pip Install lettuce

$ lettuce/path/to/example.feature is used to run tests. You can run only one test file at a time, or submit a directory name to run all the files in the directory.

In order to make the test easier to write and use, we recommend that the nosetests be installed as well:

$ pip Install nose

Attribute file

The feature file is written in English and contains the scope of the program covered by the test. It also includes a test creation task. In other words, in addition to writing tests, you have to regulate yourself to write good documentation on all aspects of the program. The advantage of doing this is that you have a good idea of the code and what to do next. As the scale of the project expands, the importance of the document gradually emerges, such as reviewing a feature or backtracking a call API, and so on.

Next, you will create an attribute file in conjunction with an instance in TDD. This example is a simple calculator written in Python and will demonstrate the basic wording of the test. The idea of a directory is to create two folders, one for apps, for placing code files such as, and the other for tests to place the attributes folder.
class Calculator (object):
  def add (self, x, y):
    number_types = (int, long, float, complex)
    if Isinstance (x, Number_types) and Isinstance (Y, number_types): return
      x + y
      raise ValueError

Feature files in the Tests/features directory Calculator.feature

Feature:as a writer for NetTuts
 I wish-Demonstrate how easy
 writing acceptance Tests in
 Python really is.< C4/>background:
  Given I am using the calculator
 scenario:calculate 2 plus 2 on our calculator
  Given I Input " 2 "Add" 2 "
  Then I should" 4 "

It is not difficult to see from this example that the description of the feature file is straightforward enough to make it visible to all members.

Three main points of the feature file:

    • Feature block (attribute blocks): This section describes the program content covered by the test group. No code is executed here, but it enables the reader to understand what characteristics are being tested.
    • Background block (background blocks): preceded by each scene (scenario) block in an attribute file. This is similar to the setup () method used to write the creation code, such as the preparation of conditions and locations.
    • Scenario block (Scene blocks): This is used to define tests. The first line is used as a description of the document again, followed by the specific content of the test. Isn't it easy to write tests in such a style?

Step (Steps) file

In addition to the feature file, the step file is also required, which is "witness the miracle of the moment." Obviously, the feature file itself will not produce any results; it requires the step file to sequentially execute the code one by one mapping with Python to have the final result output. The regular expression is applied here.

Regular expression? Wouldn't it be too complicated? In fact, in the BDD world, regular expressions are often used to catch a whole string or to grab a variable from a row. So practice makes perfect.

Regular expression? Isn't it too complicated to use in a test? In the lettuce is not, but is very simple.

The following is the preparation of the corresponding step file:

From lettuce import * to import assert_equals from
app.calculator Import calculator
@step (U ' I Am using the calculator ')
def select_calc (step):
  print (' Attempting to use calculator ... ')
  World.calc = Calculator ()
@step (U ' I input "([^"]*) "Add" ([^ "]*)"]
def given_i_input_group1_add_group1 (step, x, y):
  World.result = world.calc.add (int (x), int (y))
@step (U ' I should "([^"]+) "] def result
(step, Expected_ Result):
  Actual_result = World.result
  assert_equals (int (expected_result), Actual_result)

The first part of the file is the standard import notation. For example, the calculator access and lettuce tools are imported, as well as the assert_equals determination methods in the Nosetest package. Next, you can begin to define steps for each line of the attribute file. As mentioned earlier, regular expressions are often used to extract the entire string, in addition to the occasional need to access the variable in a row.

In this example, the @step plays a role in decoding, and the U-letter means that the expression executes in Unicode encoding. Then, a regular expression is used to match the referenced content, which is the number to add.

Then you pass the variable to the Python method, the variable name can be defined arbitrarily, and here you use X and y as the passed-in variable name for the Calculator Add method.

In addition, we need to introduce the use of world variables. World is a global container that allows variables to be used in different steps of the same scenario. Otherwise, all variables correspond only to the method in which they are available. For example, the result of the Add method is stored in a step, and the result is determined on the other side.

Execution of attributes

After both the feature file and the step file are complete, you can then run the test to see if it passes. The lettuce execution of the built-in test-run machine is simple, such as

 lettuce test/features/calculator.feature: $ lettuce tests/features/ Calculator.feature Feature:as a writer for NetTuts # tests/features/calculator.feature:1 I wish to Demonstrat E # Tests/features/calculator.feature:2 Easy Writing Acceptance tests # TESTS/FEATURES/CALCULATOR.F              Eature:3 in Python really is.
  # tests/features/calculator.feature:4 Background:given I am using the calculator # Tests/features/ Given I am using the calculator # Tests/features/ Scenario:calculate 2 plus 2 on our calculator # tes             Ts/features/calculator.feature:9 Given I input "2" Add "2" # tests/features/ Then I should "4" # tests/features/ 1 Feature (1 passed) 1 scenario (1 passed) 2 steps (2 passed) 

The output of the lettuce is very neat, it shows clearly which line of feature file code is executed, and then the successfully executed row is highlighted in green. It also shows the running attribute file and the line number, which is helpful for finding the attribute file defect row when the test fails. The end of the output is the attribute, the scene, the number of steps performed, and the number of results summarized. In this example, all the tests are passed. But if there is an error, what will lettuce do with it?

First you have to modify the code to change the Add method to two-digit subtraction:

Class Calculator (object):
  def add (self, x, y):
    number_types = (int, long, float, complex)
    if Isinstance (x, Nu Mber_types) and Isinstance (Y, number_types): Return
      raise ValueError

Run again and see how lettuce describes the error:

$ lettuce Tests/features/calculator.feature Feature:as a writer for NetTuts # Tests/features/calculator.featu Re:1 I wish to demonstrate # Tests/features/calculator.feature:2, easy writing acceptance tests # T              Ests/features/calculator.feature:3 in Python really is.
  # tests/features/calculator.feature:4 Background:given I am using the calculator # Tests/features/ Given I am using the calculator # Tests/features/ Scenario:calculate 2 plus 2 on our calculator # tes             Ts/features/calculator.feature:9 Given I input "2" Add "2" # tests/features/ Then I should "4" # tests/features/ Traceback (most recent call last): File "/users/user/.virtualenvs/bdd-in-pyt
   hon/lib/python2.7/site-packages/lettuce/ ", line 144, in __call__ ret = self.function (Self.step, *args, **kw) File "/users/user/documents/articles-nettuts/bdd_in_python/tests/features/ ", line-in-result assert_equals (int (expected_result), Actual_result) File"/system/library/frameworks/ python.framework/versions/2.7/lib/python2.7/unittest/ ", line 515, in Assertequal assertion_func (i, second , msg=msg) File "/system/library/frameworks/python.framework/versions/2.7/lib/python2.7/unittest/", line 508 , in _baseassertequal raise Self.failureexception (msg) assertionerror:4!= 0 1 feature (0 passed) 1 scenario (0 p assed) 2 Steps (1 failed, 1 passed) List of failed Scenarios:Scenario:Calculate 2 plus 2 on our calculator # TESTS/FE

It is clear that the actual result of 0 is not in conformity with the expected result 4. Lettuce clearly shows the problem, followed by debugging the error until the pass time.

Other tools
There are a number of different tools available in Python for similar testing, and these tools are basically derived from cucumber. For example:

    • Behave: This is a cucumber interface. Complete documentation, keep the update, there are a lot of supporting tools.
    • Freshen: Another cucumber interface, with complete tutorials and examples, installation methods are simple PIP.

No matter what tool you use, as long as you are skilled in using a tool, the other nature will be able to digest. The first step in success is to familiarize yourself with the tutorial documentation.


Code refactoring with confidence

The advantages of using a complete test suite are obvious. Finding a powerful test suite can make code refactoring work with less effort and confidence.

As the scale of the project continues to grow, the lack of effective tools will make backtracking and refactoring work difficult. If you have a complete set of acceptance tests that correspond to each feature one by one, you will be able to make the change work in an orderly and turbulent manner without damaging the existing functional modules.

All staff can participate in the acceptance test, will be able to greatly enhance the team fighting ability, from the beginning to the same goal forward. Programmers can focus on precise goals and avoid the need to get out of control; testers can conduct one by one reviews on feature files to achieve the ultimate in the testing process. The final form of a virtuous cycle makes every feature of the program perfectly delivered.


Together with the above process and tools, we have achieved good results in the teams we have worked in. The BDD development approach enables the entire team to remain focused, confident, active, and minimizing potential errors.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.