vedro-fn: Compact Tests, Clear Results

One of the greatest strengths of Vedro is its scenario-based approach to testing. By modeling tests as clear-cut user stories, Vedro helps you write behavior-driven tests that reflect real-world usage. However, while scenario classes are fantastic for complex tests (like end-to-end scenarios), they can sometimes feel verbose when writing smaller, more straightforward checks, such as unit tests.

Why Scenario Classes Sometimes Feel Heavy

Here is a simple example of a Vedro scenario class decoding a base64-encoded string:

<span>import</span> <span>base64</span>
<span>import</span> <span>vedro</span>
<span>class</span> <span>Scenario</span><span>(</span><span>vedro</span><span>.</span><span>Scenario</span><span>):</span>
<span>subject</span> <span>=</span> <span>"</span><span>decode base64 encoded string</span><span>"</span>
<span>def</span> <span>given</span><span>(</span><span>self</span><span>):</span>
<span>self</span><span>.</span><span>encoded</span> <span>=</span> <span>"</span><span>YmFuYW5h</span><span>"</span>
<span>def</span> <span>when</span><span>(</span><span>self</span><span>):</span>
<span>self</span><span>.</span><span>decoded</span> <span>=</span> <span>base64</span><span>.</span><span>b64decode</span><span>(</span><span>self</span><span>.</span><span>encoded</span><span>)</span>
<span>def</span> <span>then</span><span>(</span><span>self</span><span>):</span>
<span>assert</span> <span>self</span><span>.</span><span>decoded</span> <span>==</span> <span>b</span><span>"</span><span>banana</span><span>"</span>
<span>import</span> <span>base64</span>
<span>import</span> <span>vedro</span>

<span>class</span> <span>Scenario</span><span>(</span><span>vedro</span><span>.</span><span>Scenario</span><span>):</span>
    <span>subject</span> <span>=</span> <span>"</span><span>decode base64 encoded string</span><span>"</span>

    <span>def</span> <span>given</span><span>(</span><span>self</span><span>):</span>
        <span>self</span><span>.</span><span>encoded</span> <span>=</span> <span>"</span><span>YmFuYW5h</span><span>"</span>

    <span>def</span> <span>when</span><span>(</span><span>self</span><span>):</span>
        <span>self</span><span>.</span><span>decoded</span> <span>=</span> <span>base64</span><span>.</span><span>b64decode</span><span>(</span><span>self</span><span>.</span><span>encoded</span><span>)</span>

    <span>def</span> <span>then</span><span>(</span><span>self</span><span>):</span>
        <span>assert</span> <span>self</span><span>.</span><span>decoded</span> <span>==</span> <span>b</span><span>"</span><span>banana</span><span>"</span>
import base64 import vedro class Scenario(vedro.Scenario): subject = "decode base64 encoded string" def given(self): self.encoded = "YmFuYW5h" def when(self): self.decoded = base64.b64decode(self.encoded) def then(self): assert self.decoded == b"banana"

Enter fullscreen mode Exit fullscreen mode

It’s certainly clear and descriptive, but for a small test like this, the class-based approach with separate methods can be a bit more than you need. This led us to develop vedro-fn: a plugin offering a concise, function-based syntax.

Introducing vedro-fn

With vedro-fn, you can write the same test in a simpler, more streamlined style:

<span>import</span> <span>base64</span>
<span>from</span> <span>vedro_fn</span> <span>import</span> <span>scenario</span><span>,</span> <span>given</span><span>,</span> <span>when</span><span>,</span> <span>then</span>
<span>@scenario</span><span>()</span>
<span>def</span> <span>decode_base64_encoded_str</span><span>():</span>
<span>with</span> <span>given</span><span>:</span>
<span>encoded</span> <span>=</span> <span>"</span><span>YmFuYW5h</span><span>"</span>
<span>with</span> <span>when</span><span>:</span>
<span>decoded</span> <span>=</span> <span>base64</span><span>.</span><span>b64decode</span><span>(</span><span>encoded</span><span>)</span>
<span>with</span> <span>then</span><span>:</span>
<span>assert</span> <span>decoded</span> <span>==</span> <span>b</span><span>"</span><span>banana</span><span>"</span>
<span>import</span> <span>base64</span>
<span>from</span> <span>vedro_fn</span> <span>import</span> <span>scenario</span><span>,</span> <span>given</span><span>,</span> <span>when</span><span>,</span> <span>then</span>

<span>@scenario</span><span>()</span>
<span>def</span> <span>decode_base64_encoded_str</span><span>():</span>
    <span>with</span> <span>given</span><span>:</span>
        <span>encoded</span> <span>=</span> <span>"</span><span>YmFuYW5h</span><span>"</span>

    <span>with</span> <span>when</span><span>:</span>
        <span>decoded</span> <span>=</span> <span>base64</span><span>.</span><span>b64decode</span><span>(</span><span>encoded</span><span>)</span>

    <span>with</span> <span>then</span><span>:</span>
        <span>assert</span> <span>decoded</span> <span>==</span> <span>b</span><span>"</span><span>banana</span><span>"</span>
import base64 from vedro_fn import scenario, given, when, then @scenario() def decode_base64_encoded_str(): with given: encoded = "YmFuYW5h" with when: decoded = base64.b64decode(encoded) with then: assert decoded == b"banana"

Enter fullscreen mode Exit fullscreen mode

Notice how the Scenario class has been replaced with a single decorated function. The steps (given, when, then) are represented by context blocks rather than class methods. This is particularly convenient for tests that don’t need a full scenario class structure.

Key points:

  • Just add @scenario() to any function.
  • Inside the function, use with given, with when, and with then blocks to define your test flow.
  • Everything else works as you’d expect in Vedro: reporting, command line usage, test discovery, etc.

Installation

Just run:

<span>$ </span>vedro plugin <span>install </span>vedro-fn
<span>$ </span>vedro plugin <span>install </span>vedro-fn
$ vedro plugin install vedro-fn

Enter fullscreen mode Exit fullscreen mode

And that’s it! You can now import and use the @scenario, given, when, and then blocks as shown above.

Using Additional Vedro Features

Reusing Scenario Decorators

In standard Vedro, you can decorate your scenario classes with @skip, @only, and other scenario-level decorators. With vedro-fn, you can reuse these decorators by including them in the subscript of @scenario, as shown below:

<span>import</span> <span>base64</span>
<span>from</span> <span>vedro</span> <span>import</span> <span>skip</span>
<span>from</span> <span>vedro_fn</span> <span>import</span> <span>scenario</span><span>,</span> <span>given</span><span>,</span> <span>when</span><span>,</span> <span>then</span>
<span>@scenario</span><span>[</span><span>skip</span><span>]()</span>
<span>def</span> <span>decode_base64_encoded_str</span><span>():</span>
<span>with</span> <span>given</span><span>:</span>
<span>encoded</span> <span>=</span> <span>"</span><span>YmFuYW5h</span><span>"</span>
<span>with</span> <span>when</span><span>:</span>
<span>decoded</span> <span>=</span> <span>base64</span><span>.</span><span>b64decode</span><span>(</span><span>encoded</span><span>)</span>
<span>with</span> <span>then</span><span>:</span>
<span>assert</span> <span>decoded</span> <span>==</span> <span>b</span><span>"</span><span>banana</span><span>"</span>
<span>import</span> <span>base64</span>
<span>from</span> <span>vedro</span> <span>import</span> <span>skip</span>
<span>from</span> <span>vedro_fn</span> <span>import</span> <span>scenario</span><span>,</span> <span>given</span><span>,</span> <span>when</span><span>,</span> <span>then</span>

<span>@scenario</span><span>[</span><span>skip</span><span>]()</span>
<span>def</span> <span>decode_base64_encoded_str</span><span>():</span>
    <span>with</span> <span>given</span><span>:</span>
        <span>encoded</span> <span>=</span> <span>"</span><span>YmFuYW5h</span><span>"</span>

    <span>with</span> <span>when</span><span>:</span>
        <span>decoded</span> <span>=</span> <span>base64</span><span>.</span><span>b64decode</span><span>(</span><span>encoded</span><span>)</span>

    <span>with</span> <span>then</span><span>:</span>
        <span>assert</span> <span>decoded</span> <span>==</span> <span>b</span><span>"</span><span>banana</span><span>"</span>
import base64 from vedro import skip from vedro_fn import scenario, given, when, then @scenario[skip]() def decode_base64_encoded_str(): with given: encoded = "YmFuYW5h" with when: decoded = base64.b64decode(encoded) with then: assert decoded == b"banana"

Enter fullscreen mode Exit fullscreen mode

This function is now skipped by the test runner, exactly like a skipped scenario class.

Parametrizing Your Tests

Need to test a variety of inputs and expected outputs? Parametrization works almost the same way it does in standard Vedro — just pass a list of params to the @scenario() decorator:

<span>import</span> <span>base64</span>
<span>from</span> <span>vedro</span> <span>import</span> <span>params</span>
<span>from</span> <span>vedro_fn</span> <span>import</span> <span>scenario</span><span>,</span> <span>when</span><span>,</span> <span>then</span>
<span>@scenario</span><span>([</span>
<span>params</span><span>(</span><span>"</span><span>YmFuYW5h</span><span>"</span><span>,</span> <span>b</span><span>"</span><span>banana</span><span>"</span><span>),</span>
<span>params</span><span>(</span><span>""</span><span>,</span> <span>b</span><span>""</span><span>),</span>
<span>])</span>
<span>def</span> <span>decode_base64_encoded_str</span><span>(</span><span>encoded</span><span>,</span> <span>expected</span><span>):</span>
<span>with</span> <span>when</span><span>:</span>
<span>decoded</span> <span>=</span> <span>base64</span><span>.</span><span>b64decode</span><span>(</span><span>encoded</span><span>)</span>
<span>with</span> <span>then</span><span>:</span>
<span>assert</span> <span>decoded</span> <span>==</span> <span>expected</span>
<span>import</span> <span>base64</span>
<span>from</span> <span>vedro</span> <span>import</span> <span>params</span>
<span>from</span> <span>vedro_fn</span> <span>import</span> <span>scenario</span><span>,</span> <span>when</span><span>,</span> <span>then</span>

<span>@scenario</span><span>([</span>
    <span>params</span><span>(</span><span>"</span><span>YmFuYW5h</span><span>"</span><span>,</span> <span>b</span><span>"</span><span>banana</span><span>"</span><span>),</span>
    <span>params</span><span>(</span><span>""</span><span>,</span> <span>b</span><span>""</span><span>),</span>
<span>])</span>
<span>def</span> <span>decode_base64_encoded_str</span><span>(</span><span>encoded</span><span>,</span> <span>expected</span><span>):</span>
    <span>with</span> <span>when</span><span>:</span>
        <span>decoded</span> <span>=</span> <span>base64</span><span>.</span><span>b64decode</span><span>(</span><span>encoded</span><span>)</span>

    <span>with</span> <span>then</span><span>:</span>
        <span>assert</span> <span>decoded</span> <span>==</span> <span>expected</span>
import base64 from vedro import params from vedro_fn import scenario, when, then @scenario([ params("YmFuYW5h", b"banana"), params("", b""), ]) def decode_base64_encoded_str(encoded, expected): with when: decoded = base64.b64decode(encoded) with then: assert decoded == expected

Enter fullscreen mode Exit fullscreen mode

This will generate separate test cases for each set of parameters passed in.

Current Limitations

While vedro-fn provides nearly all the features you know and love from Vedro, there are a couple of considerations:

  1. No Scope Support: Scope-related functionality is not supported because there is no underlying scenario instance to attach them to.
  2. No Step Function Decorators: Since steps (given, when, then) are not individual methods in vedro-fn but rather code blocks within a function, you cannot decorate them separately.

Despite these limitations, everything else — various reporters, parallel execution, external plugins — works seamlessly with vedro-fn.

Share Your Feedback!

vedro-fn is an experimental plugin. If you find it helpful for tidying up smaller tests or want to see more functionality added, let us know! Your feedback will determine whether vedro-fn becomes a fully supported part of the Vedro core.

原文链接:vedro-fn: Compact Tests, Clear Results

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
Put blinders on to those things that conspire to hold you back, especially the ones in your own head.
不要去想那些阻碍你的事,尤其是那些自己想象出来的事
评论 抢沙发

请登录后发表评论

    暂无评论内容