byexamples / byexamples/byexample

Defer examples to last for cleaning up tasks (like the Go feature defer)

Open
#127 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Python
Stars
67
Forks
9
PR merge metrics
No merged PRs in 30d

Description

**Describe the feature you'd like**

You can tag an example with `+defer` and its execution will be deferred at the end. If multiple examples have `+defer`, the execution order will be reversed as they were seen: first example seen last executed.

This is based on the [Go lang's defer feature](https://blog.golang.org/defer-panic-and-recover)

For example:

```python
>>> f = open()
>>> f.close() # byexample: +defer
>>> c = connect()
>>> c.close() # byexample: +defer

>>> do_something(f, c)
```

In the above example the examples will be executed like if they were written like this:

```python
>>> f = open()
>>> c = connect()

>>> do_something(f, c)

>>> c.close()
>>> f.close()
```

On failures, the fail fast mode enters in action (examples are skipped). For example if `c = connect()` fails, the equivalent execution would be:

```python
>>> f = open()
>>> c = connect() # <-- Imagine that this example fails

>>> do_something(f, c) # <-- This will be skipped

>>> c.close() # <-- This will be skipped
>>> f.close() # <-- This will NOT be skipped
```

The reasoning is that `c.close() # byexample: +defer` was seen *after* one example failed and therefore it should be skipped while `f.close() # byexample: +defer` was seen *before* the failing example so it should be executed as usual.

The equivalent file would be (note the `skip`):

```python
>>> f = open()
>>> c = connect() # <-- Imagine that this example fails

>>> do_something(f, c) # <-- This will be skipped

>>> c.close() # byexample: +skip # <-- This will be skipped
>>> f.close() # byexample: -skip # <-- This will NOT be skipped
```

`+defer` not only *"reschedule"* the example but also adds `-skip` to it if it was seen before a failing test or `+skip` it it was seen after.

An explicit `+skip` or `-skip` could be used to ensure a particular flag and it should be honored regardless of the default behavior of `+defer`: if `+skip +defer` is used, the example is deferred but always is skipped for example.

## Additional links (experience from people using `golang`)

The good, the bad and the ugly of `defer`:

- https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md
- https://go.googlesource.com/proposal/+/master/design/go2draft-error-values-overview.md
- https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling.md
- https://golang.org/doc/effective_go#errors

Not related, but interesting articles:

- https://devblogs.microsoft.com/oldnewthing/20050114-00/?p=36693
- https://devblogs.microsoft.com/oldnewthing/20040422-00/?p=39683

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.