Package: pyspock
spockpyspockis a BDD-style developer testing and specification framework for Python, and this is an implementation of thespock.An example of simple test:importpytest@pytest.mark.spock("maximum of{a}and{b}is{c}")deftest_maximum():defexpect(a,b,c):assertmax(a,b)==cdefwhere(_,a,b,c):_|a|b|c_|3|7|7_|5|4|5_|9|9|9If you are using vscode, you can find there will be 3 test cases.InstallationpipinstallpyspockNote the minimum version of pytest is 6.2.4.MarkIt is easy to define spock test cases, just usepytest.mark.spockto decorate your test function.@pytest.mark.spockdeftest_bigger():defexpect():assert2>1spock mark also accepts one parameter, which is used to render identity for each iteration arguments.@pytest.mark.spock("{a}>{b}")deftest_bigger():defexpect(a,b):asserta>bdefwhere(_,a,b):_|a|b_|7|3_|5|2BlocksThere are six kinds of blocks:given,when,then,expect,cleanupandwhereblocks. Each block is a function defined by its name.A test function must have at least one explicit block. Blocks divide a test function into distinct sections, and cannot be nested.The above picture shows how blocks map to the conceptual phases of a feature function. The where block has a special role, which will be revealed shortly. But first, let’s have a closer look at the other blocks.1. Given block@pytest.mark.spockdeftest_demo():defgiven(me):me.stack=[]me.elem=1Thegivenblock is where you do any setup work for the feature that you are describing. It may not be preceded by other blocks. Agivenblock doesn’t have any special semantic, and it is optional and may be omitted.Thegivenaccepts all pytest fixtures, besides it has a special fixture namedme, which can take any setup values. Those setup values can be as fixtures in other blocks except thewhereblock.2. When and Then blocks@pytest.mark.spockdeftest_append_element():defgiven(me):me.stack=[]me.elem=1defwhen(stack,elem):# stimulusstack.append(elem)defthen(stack,elem):# responseassertlen(stack)==1assertstack.pop()==elemThewhenandthenblocks always occur together. They describe a stimulus and the expected response. Whereas when blocks may contain arbitrary code, then blocks are restricted to conditions, exception conditions, interactions.Thethenhas a special fixture namedexcinfo, which represents whether thewhenblock raises exception. If thewhenblock not raises exception, thenexcinfowill be None. Theexcinfotype isExceptionInfo.@pytest.mark.spockdeftest_zero_division():defwhen():1/0defthen(excinfo):assertexcinfo.typeisZeroDivisionError3. Expect blockAnexpectblock is more limited than athenblock in that it may only contain conditions and variable definitions. It is useful in situations where it is more natural to describe stimulus and expected response in a single expression. For example, compare the following two attempts to describe themaxfunction:@pytest.mark.spockdeftest_maximum():defgiven(me):me.x=max(1,2)defthen(x):assertx==2equals to:@pytest.mark.spockdeftest_maximum():defexpect():assertmax(1,2)==24. Cleanup block@pytest.mark.spockdeftest_file():defgiven(me):me.file=open("test.txt","r+")defwhen(file):file.write("hello")defthen(file):file.seek(0)assertfile.read()=="hello"defcleanup(file):file.close()cleanupblock is used to free any resources used by a test case, and will run even if (a previous part of) the test case has produced an exception. As a consequence, acleanupblock must be coded defensively.5. Where blockAwhereblock always comes last in a test function. It is used to write data-driven feature functions. To give you an idea how this is done, have a look at the following example:@pytest.mark.spock("max({a},{b}) =={c}")deftest_maximum_of_two_numbers():defexpect(a,b,c):assertmax(a,b)==cdefwhere(a,b,c):a<<[5,3]b<<[1,9]c<<[5,9]Thiswhereblock effectively creates two "versions" of the feature functions: One where a is 5, b is 1, and c is 5, and another one where a is 3, b is 9, and c is 9.Although it is declared last, the where block is evaluated before the feature function containing it runs.Data tablewhereblock support another syntax to specify the data.@pytest.mark.spock("max({a},{b}) =={c}")deftest_maximum_of_two_numbers():defexpect(a,b,c):assertmax(a,b)==cdefwhere(_,a,b,c):_|a|b|c_|5|1|5_|3|9|9The first line of the table, called the table header, declares the data variables. The subsequent lines, called table rows, hold the corresponding values. For each row, the feature method will get executed once; we call this an iteration of the function. If an iteration fails, the remaining iterations will nevertheless be executed. All failures will be reported.You can also split the data table into multiple parts.@pytest.mark.spock("max({a},{b}) =={c}")deftest_maximum_of_two_numbers():defexpect(a,b,c):assertmax(a,b)==cdefwhere(_,a,b,c):_|a|b_|5|1_|3|9_|c_|5_|9Accessing other data variablesdefwhere(_,a,b):_|a|b_|5|a+1_|3|a+2variable supports all operators like+,-,*,/,%,**,//,==,!=,<,<=,>,>=and so on.adapter blackif you are usingblack, you should close fmt when use data table.defwhere(_,a,b,c):# fmt: off_|a|b|c_|5|a+1|4_|3|a+2|2# fmt: on6. ConclusionblockSupport fixturesSpecial fixturesOptionalgiven✅me✅when✅❎✅then✅excinfowhenexpectblock existsexpect❎❎whenthenblock existscleanup✅❎✅where✅_✅