Search code examples
pythonunit-testing

Is there a Spock-like testing library for Python


I've worked with Spock and loved the 'where' clause, which allows you to easily exercise the test case with multiple inputs and outputs. For example:

class HelloSpock extends spock.lang.Specification {
    def "length of Spock's and his friends' names"() {
        expect:
            name.size() == length

        where:
            name     | length
            "Spock"  | 5
            "Kirk"   | 4
            "Scotty" | 6
    }
} 

Is there something similar for Python?


Solution

  • Yes, there is!

    I'm the author of Nimoy - a framework that was built with the purpose of being Spock for Python.

    You can create data driven tests:

    from nimoy.specification import Specification
    
    class MySpec(Specification):
    
        def my_feature_method(self):
            with given:
                a = value_of_a
                b = value_of_b
    
            with expect:
                (a * b) == expected_value
    
            with where:
                value_of_a | value_of_b | expected_value
                1          | 10         | 10
                2          | 20         | 40
    

    You can stage mocks:

    from unittest import mock
    from nimoy.specification import Specification
    
    class MySpec(Specification):
    
        def my_feature_method(self):
            with setup:
                the_mock = mock.Mock()
    
            with when:
                the_mock.some_method() << [5, 6, 7]
    
            with then:
                the_mock.some_method() == 5
                the_mock.some_method() == 6
                the_mock.some_method() == 7
    

    And we have pretty mock assertions as well:

    from unittest import mock
    from nimoy.specification import Specification
    
    class MySpec(Specification):
    
        def my_feature_method(self):
            with setup:
                the_mock = mock.Mock()
    
            with when:
                the_mock.some_method('abcd', True)
    
            with then:
                1 * the_mock.some_method('abcd', True)