# E: Test Which Expectations are Met

## Description

Performs a unit test and summarises the results.

## Usage

``` r
E(
  expr,
  ...,
  value_comparer = getOption("realtest_value_comparer", identical),
  sides_comparer = getOption("realtest_sides_comparer", sides_similar),
  postprocessor = getOption("realtest_postprocessor", failstop)
)
```

## Arguments

|                  |                                                                                                                                                                                                                                                                                                                                    |
|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `expr`           | an expression to be recorded (via [`R`](R.md)) and and compared with the prototypes                                                                                                                                                                                                                                                |
| `...`            | a sequence of 1 or more (possibly named) prototypes constructed via [`R`](R.md) or [`P`](P.md) (objects which are not of class `realtest_descriptor` will be passed to [`P`](P.md)); arguments whose names start with a dot (like `.label=value`) can be used to introduce metadata (e.g., additional details in natural language) |
| `value_comparer` | a two-argument function used (unless overridden by the prototype) to compare the values with each other, e.g., [`identical`](https://stat.ethz.ch/R-manual/R-devel/library/base/help/identical.html) or [`all.equal`](https://stat.ethz.ch/R-manual/R-devel/library/base/help/all.equal.html)                                      |
| `sides_comparer` | a two-argument function used (unless overridden by the prototype) to compare the side effects (essentially: two lists) with each other, e.g., [`sides_similar`](comparers.md) or [`ignore_differences`](comparers.md)                                                                                                              |
| `postprocessor`  | a function to call on the generated `realtest_result`, e.g., [`failstop`](postprocessors.md)                                                                                                                                                                                                                                       |

## Details

Each expression in the R language has a range of possible effects. The direct effect corresponds to the value generated by evaluating the expression. Side effects may include errors, warnings, text printed out on the console, etc., see [`P`](P.md) and [`R`](R.md).

Arguments passed via `...` whose names do not start with a dot should be objects of class `realtest_descriptor` (otherwise they are passed to [`P`](P.md)). They define the prototypes against which the object generated by `expr` will be tested.

`value_comparer` and `sides_comparer` are 2-ary functions that return `TRUE` if two objects/side effect lists are equivalent and a character string summarising the differences (or any other kind or object) otherwise.

A test case is considered met, whenever `value_comparer(prototype[["value"]], object[["value"]])` and `sides_comparer(prototype[["sides"]], object[["sides"]])` are both `TRUE` for some `prototype`. The comparers may be overridden on a per-prototype basis, though. If `prototype[["value_comparer"]]` or `prototype[["sides_comparer"]]` are defined, these are used instead.

## Value

The function creates an object of class `realtest_result`, which is a named list with at least the following components:

-   `object` -- an object of class `realtest_descriptor`, ultimately [`R(expr)`](R.md),

-   `prototypes` -- a (possibly named) list of objects of class `realtest_descriptor` that were passed via `...`,

-   `matches` -- a (possibly empty) numeric vector of the indexes of the prototypes matching the object (can be named),

-   `.dotted.names` -- copied as-is from the arguments of the same name.

This object is then passed to the `postprocessor` which itself becomes responsible for generating the output value to be returned by the current function (and, e.g., throwing an error if the test fails).

## Author(s)

[Marek Gagolewski](https://www.gagolewski.com/)

## See Also

The official online manual of <span class="pkg">realtest</span> at <https://realtest.gagolewski.com/>

Related functions: [`P`](P.md), [`R`](R.md), [`test_dir`](test_dir.md)

## Examples




```r
# the default result postprocessor throws an error on a failed test:
E(E(sqrt(4), P(7)), P(error=TRUE, stdout=TRUE))
E(sqrt(4), 2.0)  # the same as E(sqrt(4), P(2.0))
E(sin(pi), 0.0, value_comparer=all.equal)  # almost-equal
E(
  sample(c("head", "tail"), 1),
  .description="this call has two possible outcomes",
  "head",  # first prototype
  "tail"   # second prototype
)
E(sqrt(-1), P(NaN, warning=TRUE))  # a warning is expected
E(sqrt(-1), NaN, sides_comparer=ignore_differences) # do not test side effects
E(sqrt(-1), P(NaN, warning=NA))  # ignore warnings
E(
  paste0(1:2, 1:3),                  # expression to test - concatenation
  .description="partial recycling",  # info - what behaviour are we testing?
  best=P(                            # what we yearn for (ideally)
    c("11", "22", "13"),
    warning=TRUE
  ),
  pass=c("11", "22", "13"),          # this is the behaviour we have now
  bad=P(error=TRUE)                  # avoid regression
)
e <- E(sin(pi), best=0.0, pass=P(0.0, value_comparer=all.equal),
  .comment="well, this is not a symbolic language after all...")
print(e)
## $object
## $value
## [1] 1.224647e-16
## 
## $expr
## sin(pi)
## 
## $args
## $args$pi
## [1] 3.141593
## 
## 
## attr(,"class")
## [1] "realtest_descriptor" "realtest"           
## 
## $prototypes
## $prototypes$best
## $value
## [1] 0
## 
## $differences
## [1] "objects are different"
## 
## attr(,"class")
## [1] "realtest_descriptor" "realtest"           
## 
## $prototypes$pass
## $value
## [1] 0
## 
## $value_comparer
## function (target, current, ...) 
## UseMethod("all.equal")
## <bytecode: 0x5641c571c870>
## <environment: namespace:base>
## 
## attr(,"class")
## [1] "realtest_descriptor" "realtest"           
## 
## 
## $matches
## pass 
##    2 
## 
## $.comment
## [1] "well, this is not a symbolic language after all..."
## 
## attr(,"class")
## [1] "realtest_result" "realtest"
```
