Behavior Driven Development and Unit Testing in Python [closed]

We might be interested in starting to incorporate a unit test suite to our project, which is coded in Python (and it uses Redis, PostgreSQL and some third-party libraries, if that bears into the solution). The benefits we want to achieve are:

  1. Once the project is up to speed, we want to be able to specify new behavior quickly and efficiently, to help improve communication and team productivity. Read: We want BDD, but have already started coding without it.
  2. Excellent textual support (i.e. the tests can be read almost as natural text), so as to make it easier to write and read tests.
  3. Ability to automatically run tests (at the very least, to be able to include the running in a Bash script or something like that). We use Windows and Linux for development, and Linux servers, so Linux support is our primary requirement.
  4. Integration with github. I don’t know if it is possible, but I’ve seen some projects in github which have a “Passing” or “Failing” status on them and it would be great to have that for our project.

What are good tools / libraries that can help us do this, and, most importantly, what are good ways to incorporate BDD into a Python project?

Thank you very much! Any suggestions are appreciated.

2

Try out pyspecs. Making tests easy to read and constantly running during development were two of my main goals in creating this project.

Test Code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>from pyspecs import given, when, then, and_, the, this
with given.two_operands:
a = 2
b = 3
with when.supplied_to_the_add_function:
total = a + b
with then.the_total_should_be_mathmatically_correct:
the(total).should.equal(5)
with and_.the_total_should_be_greater_than_either_operand:
the(total).should.be_greater_than(a)
the(total).should.be_greater_than(b)
with when.supplied_to_the_subtract_function:
difference = b - a
with then.the_difference_should_be_mathmatically_correct:
the(difference).should.equal(1)
</code>
<code>from pyspecs import given, when, then, and_, the, this with given.two_operands: a = 2 b = 3 with when.supplied_to_the_add_function: total = a + b with then.the_total_should_be_mathmatically_correct: the(total).should.equal(5) with and_.the_total_should_be_greater_than_either_operand: the(total).should.be_greater_than(a) the(total).should.be_greater_than(b) with when.supplied_to_the_subtract_function: difference = b - a with then.the_difference_should_be_mathmatically_correct: the(difference).should.equal(1) </code>
from pyspecs import given, when, then, and_, the, this

with given.two_operands:
    a = 2
    b = 3

    with when.supplied_to_the_add_function:
        total = a + b

        with then.the_total_should_be_mathmatically_correct:
            the(total).should.equal(5)

        with and_.the_total_should_be_greater_than_either_operand:
            the(total).should.be_greater_than(a)
            the(total).should.be_greater_than(b)

    with when.supplied_to_the_subtract_function:
        difference = b - a

        with then.the_difference_should_be_mathmatically_correct:
            the(difference).should.equal(1)

Console Output:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code># run_pyspecs.py
| • given two operands
| • when supplied to the add function
|then the total should be mathmatically correct
| • and the total should be greater than either operand
| • when supplied to the subtract function
|then the difference should be mathmatically correct
(ok) 6 passed (6 steps, 1 scenarios in 0.0002 seconds)
</code>
<code># run_pyspecs.py | • given two operands | • when supplied to the add function | • then the total should be mathmatically correct | • and the total should be greater than either operand | • when supplied to the subtract function | • then the difference should be mathmatically correct (ok) 6 passed (6 steps, 1 scenarios in 0.0002 seconds) </code>
# run_pyspecs.py

  | • given two operands 
  |   • when supplied to the add function 
  |     • then the total should be mathmatically correct 
  |     • and the total should be greater than either operand 
  |   • when supplied to the subtract function 
  |     • then the difference should be mathmatically correct 

(ok) 6 passed (6 steps, 1 scenarios in 0.0002 seconds)

2

While there are BDD frameworks like lettuce or behave (which you better choose by their documentation and examples), you mentioned that you’ve started without that. So my answer will be related more to this situation.

Original BDD has started with fork of JUnit, which, instead of asking you to name your tests with “testSomething” asked you to name them “shouldDoSomething”. That’s how you were supposed to be kept focused on things.

So I went the same way in my project. I just started to name tests starting with “test_should_…” and try to give them descriptive names. That’s how you’re still doing BDD, you’re still focused on what exactly should that test do, and it’s easy to write something that will convert your test names into normal sentences (if you’ll need to, of course). I find this approach a silver bullet since (especially in scripted languages) I never want to waste time on useless names (like test name in case of those BDD frameworks on top).

2

I’ve been working on a BDD framework called Contexts, inspired by C#’s Machine.Specifications.

Contexts encourages you to write descriptive user-centric sentences for your tests (which is what BDD is all about, really) by spreading out test-cases across a whole class. The arrange/act/assert phases of the test are put in individual short methods, and Contexts figures out which method is which based on their names.

A picture speaks a thousand words, so here’s an example from the readme:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>import requests
class WhenRequestingAResourceThatDoesNotExist:
def given_that_we_are_asking_for_a_made_up_resource(self):
self.uri = "http://www.github.com/itdontexistman"
self.session = requests.Session()
def because_we_make_a_request(self):
self.response = self.session.get(self.uri)
def the_response_should_have_a_status_code_of_404(self):
assert self.response.status_code == 404
def the_response_should_have_an_HTML_content_type(self):
assert self.response.headers['content-type'] == 'text/html'
def cleanup_the_session(self):
self.session.close()
</code>
<code>import requests class WhenRequestingAResourceThatDoesNotExist: def given_that_we_are_asking_for_a_made_up_resource(self): self.uri = "http://www.github.com/itdontexistman" self.session = requests.Session() def because_we_make_a_request(self): self.response = self.session.get(self.uri) def the_response_should_have_a_status_code_of_404(self): assert self.response.status_code == 404 def the_response_should_have_an_HTML_content_type(self): assert self.response.headers['content-type'] == 'text/html' def cleanup_the_session(self): self.session.close() </code>
import requests

class WhenRequestingAResourceThatDoesNotExist:
    def given_that_we_are_asking_for_a_made_up_resource(self):
        self.uri = "http://www.github.com/itdontexistman"
        self.session = requests.Session()

    def because_we_make_a_request(self):
        self.response = self.session.get(self.uri)

    def the_response_should_have_a_status_code_of_404(self):
        assert self.response.status_code == 404

    def the_response_should_have_an_HTML_content_type(self):
        assert self.response.headers['content-type'] == 'text/html'

    def cleanup_the_session(self):
        self.session.close()

Contexts also has a number of modern features like parametrised tests, ‘assertion-rewriting’ (inspired by py.test), and a plugin framework.

I’ve used Contexts to test itself, as well as on a few other projects (even non-Python projects), and found it to yield understandable, behavioural tests at all levels of the testing triangle (unlike unittest which was not designed for acceptance testing, or Lettuce which was not designed for unit testing).

1

I think you should try Morelia:
https://morelia.readthedocs.org/en/latest/

It passes your 4-point requirements list:

  1. It’s BDD tool built on Python’s unittests module
  2. Executed tests are textual description.
  3. If you can automatically run traditional Unit Tests then Morelia can be run same way.
  4. I think the most common CI for github is Travis-CI which can run unit tests so that it can run Morelia.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật