test-drive icon indicating copy to clipboard operation
test-drive copied to clipboard

Simplify `check` and `return` handling

Open certik opened this issue 4 years ago • 1 comments
trafficstars

Why not simplify:

            call check(error, all(input == expected))
            if (allocated(error)) return

to:

            if (check(error, all(input == expected))) return

Beyond that, the only other way to simplify is using macros, but I like that this is very usable without macros.

certik avatar Sep 10 '21 18:09 certik

Using subroutines instead of functions for test-drive was a deliberate choice, but I'm open to discuss and reevaluate this decision.

The optimal unit test should not require a return statement at all. Instead we should encourage aiming for smaller tests, the best in my opinion is to have a unit test like

subroutine test_something(error)
  type(error_type), allocatable, intent(out) :: error
  ! ... calculate something
  call check(error, actual, expected)
end subroutine test_something

In this scenario there is no need for a return statement at all. We get one test which tests exactly one thing.

In reality, of course, things are more complicated and one might need several check calls in one subroutine, especially if IO resources are involved, which have to be closed again. An example for such case would be test_stdlib_bitset_64. In this case one would end up with constructs like if (.not.check(error, ...)) then to continue testing, which I find unintuitive.

Maybe Brad @everythingfunctional can comment on this issue and his choice for vegetables, which is based on a somewhat similar logic to organize unit tests.

awvwgk avatar Sep 10 '21 20:09 awvwgk