Skip to content

Improving call support #132

Open
Open
@reedacartwright

Description

@reedacartwright

I have been playing around with extending tinytest, and I noticed that the "call" argument in tinytest() gets overwritten by the function constructed by capture(). Additionally format.tinytest() has specific logic to reconstruct the call from the trace if needed. I assume that having capture() control the "call" is due to sys.call(sys.parent(1)), returning fun(...) for captured functions.

I was thinking of a solution around these issues, and decided to make capturing functions pass their call down to the captured functions. This allows expectations or anything that calls tinytest() to control what call looks like, making it easier to nest expectations.

An minimal example is below:

# Simple tinytest constructor
tinytest <- function(result, call = sys.call(sys.parent(1)), ...) {
    force(call)
    trace <- sys.calls()
    structure(result, class = "tinytest", call = call, trace = trace, ...)
}

# Expectation that will be captured
expect_example <- function(...) {
    tinytest(TRUE, ...)
}

# Simple capture function
capture <- function(fun) {
    force(fun)

    function(...) {
        # Create a local variable that matches the name of the function that was called.
        # Assign the captured function to that name.
        # Evaluate the original call to pass it into the captured function.
        call <- sys.call()
        assign(as.character(call[[1]]), fun)
        out <- eval(call)
        ## do stuff to out here.
        attr(out, "captured") <- TRUE
        out
    }
}

So now when a captured function is called, sys.call(sys.parent(1)) behaves as expected. This allows the call attribute to be the same for captured and uncaptured functions.

expect_example(a=1, b=2) # call is `expect_example(a=1,b=2)`

expect_example <- capture(expect_example)
expect_example(a=1, b=2) # call is `expect_example(a=1,b=2)`

expect_example_alt <- expect_example
expect_example_alt(a=1, b=2) # call is `expect_example_alt(a=1,b=2)`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions