[PATCH] Add a TEST-OP-TEST-FAILURE condition for test libraries to sub-class

Anton Vodonosov avodonosov at yandex.ru
Tue Oct 8 04:18:27 UTC 2019


Also, the library can provide serialization of the common test result to files,
thus simplifying implementation of the test-report-op, as Fare mentions.

08.10.2019, 07:17, "Anton Vodonosov" <avodonosov at yandex.ru>:
> Vladmir, the library content is not just the signal trick (or special vars).
>
> It defines the unified common test result representation, provides a bridge
> between the protocol test libraries "signal" their result and the protocol
> the user running tests consumes the results. The library can also
> provide means to create the common test results as a normal return value;
> or maybe deliver it through a stack-based mechanism, but explicitly,
> without relying on test frameworks to do it automatically (in some cases
> I anticipate explicit creation of the result will be more convenient)
>
> And yes, the most important, adding such functionality into the public ASDF API
> requires too much upfront thinking. After separate library experiments with
> the approach and stabilizes, ASDF can incorporate, or officially refer it.
>
> As Robert mentions in the pull request, having this functionality in new
> versions of ASDF would require the consumer to check feature flags
> in their code. In the case of a separate library, the consumer can just load
> this library, and it will work even with old versions of ASDF.
>
> 04.10.2019, 06:39, "Vladimir Sedach" <vas at oneofus.la>:
>>  Robert Goldman <rpgoldman at sift.info> writes:
>>
>>>>   - success should also be signaled, so we can distinguish a version
>>>>   where
>>>>     this new protocol is not implemented from the version where tests
>>>>   pass
>>>
>>>   This requires a protocol where ASDF can "know" when the test op is
>>>   done, so that it can distinguish "has succeeded" from "has not failed
>>>   yet." It's possible that this could be managed by the test op on the
>>>   system as a whole, but the design must consider the possibility that
>>>   the test-op may be implemented so that:
>>>
>>>   1. Multiple calls are made into the test library (possibly even
>>>   multiple test libraries are used)
>>>   2. TEST-OP may involve invoking test operation on systems depended on
>>>   (e.g., where a system has subsystems).
>>
>>  There would be three situations here:
>>
>>  1. OPERATE TEST-OP returns with no relevant conditions signaled. You
>>  can infer that the condition protocol is not implemented.
>>  2. OPERATE TEST-OP returns and one or more test failure conditions
>>  are signaled.
>>  3. OPERATE TEST-OP returns and only test success conditions are
>>  signaled.
>>
>>>>   - the minimal requirement is a success / failure designator, the
>>>>   failed
>>>>     test names can be optional
>>>
>>>   - Additional requirement: the condition should support accessing both
>>>   a long and a short form report. In degenerate implementations, these
>>>   can, of course, be identical.
>>
>>  What would the long and short form reports look like?
>>
>>>>     some corner cases. Still, even if we expect test results being
>>>>   signalled
>>>>     multiple times during a test-op, it would be good to provide a
>>>>   wrapper
>>>>     which aggregates them into a single return value.
>>>>
>>>>           (common-test-results:collect (asdf:test-system "my-system"))
>>>
>>>   This would require that the test library provide an extensible
>>>   protocol for fusing together multiple test results.
>>
>>  It is simpler than that: take all of the conditions, add the number
>>  of tests executed, and append all of the test failure lists. No need
>>  for library-specific code.
>>
>>>   And note that the above suggestion will not work, because ASDF does
>>>   not ever *return* a value from operating. This has to do with the
>>>   way ASDF creates a plan and then executes it. The plan doesn't
>>>   support a notion of "return value," so the only way to get
>>>   information out of ASDF is through conditions.
>>
>>  What COMMON-TEST-RESULTS:COLLECT would do is handle and coalesce
>>  multiple conditions and re-signal a single condition.
>>
>>>   I agree -- I think `TRIVIAL-TEST-INTERFACE` might be a better first
>>>   step. I suppose the alternative rationale is that a test interface
>>>   that was *not* intended for incorporation into ASDF would be able to
>>>   just *return* things, instead of *signaling* them.
>>
>>  The point is, systems already define TEST-OP. I am trying to use
>>  that. The code that uses TEST-OP can do whatever it needs to, but the
>>  communication between that code and the test libraries has to be done
>>  by stack-based mechanisms like conditions or special variables.
>>
>>>   That is true, but it's also true that it would require special
>>>   condition-handling to fit test results into continuous integration
>>>   -- programmers would no longer be able to just use `quit-on-error`,
>>>   which is a very handy way to turn a lisp test into something that
>>>   works in Jenkins or, for that matter, any infrastructure based on
>>>   shell scripting.
>>
>>  Right now errors are not signaled on test failures in most
>>  definitions of TEST-OP I looked at, so this is not something that is
>>  currently going on. Neither is this something that would stop working
>>  for anyone that has the signal-error-on-failure flags set for their
>>  test library, or is throwing errors explicitly.
>>
>>>   I'd rather have to write code to handle errors when I *don't* want
>>>   them, than have test failure not be an error.
>>>
>>>   If I'm running interactively, it's not a bother to deal with this as
>>>   an error condition -- I can easily get out of the debugger. But
>>>   writing a lot of code to catch `TEST-FAILURE` conditions and
>>>   translate them into exit with non-zero status would be a pain.
>>
>>  Test libraries already have flags whether to signal errors on test
>>  failures or not. Having the condition be a sub-class of error would
>>  not only be annoying in the REPL, it would break whatever test
>>  automation code uses these flags, and it would change the behavior of
>>  TEST-OP, most of whose callers do not expect it to signal errors on
>>  test failures right now. This is a lot of breakage of thousands of
>>  existing systems, just to avoid doing the following in a few test
>>  automation scripts:
>>
>>  (handler-case
>>      (asdf:test-system "some-system")
>>    (asdf:test-op-test-failures (condition)
>>      (princ condition uiop:*stderr*)
>>      (uiop:quit 1)))
>>
>>>>   - slot for the failing asdf system could probably be avoided,
>>>>     the list failed test names could be enough, if the names are
>>>>   "fully qualified"
>>>>     i.e. include package or system name.
>>>
>>>   I don't think we can make any assumptions about the above -- there's
>>>   no rule about how a programmer can assign test names in a library
>>>   like FiveAM to packages.
>>
>>  FiveAM test names are symbols, so they already get printed with their
>>  package name in the implementation I did for FiveAM, without any
>>  extra work.
>>
>>>   I would note also that getting a new library into Quicklisp for this
>>>   is going to be a lot easier than getting a new ASDF into Quicklisp:
>>>   Xach has for years refused to update the ASDF version in Quicklisp,
>>>   and I don't see any reason to believe this will change.
>>
>>  As I mentioned before, I would like to avoid creating a whole library
>>  out of something that is a work-around to OPERATE not returning
>>  results.
>>
>>  Unfortunately, it seems there are both social and technical problems
>>  with updating ASDF. In particular I do not see a good mechanism for
>>  advertising the availability of this condition protocol to test
>>  libraries (there does not seem to be an established way of
>>  advertising new ASDF functionality other than the :ASDF3.3 :ASDF3.2
>>  etc. keywords in *FEATURES*).
>>
>>  As Anton pointed out, this necessitates the libraries signaling a
>>  condition for test success, which necessitates a function like
>>  COMMON-TEST-RESULTS:COLLECT. While writing an implementation of that
>>  function, I realized I would need to add continue restarts (the only
>>  way to handle a condition without affecting control flow).
>>
>>  Take all of this together, and it becomes apparent that avoiding ASDF
>>  to provide a more useful TEST-OP is, ironically, the way to go. It is
>>  simpler to drive communications down the stack by binding special
>>  variables to act as accumulators, than it is communicating up the
>>  stack with signals, handlers, and restarts. Putting this into a
>>  library means TEST-OP would still retain a use as a way to trigger
>>  test runs without knowing details about either the tests or the test
>>  library (the first half of this proposal), but it will unfortunately
>>  mean that ASDF will continue to have no say about what the effects of
>>  TEST-OP are (the second half of this proposal).
>>
>>  --
>>  Vladimir Sedach
>>  Software engineering services in Los Angeles https://oneofus.la



More information about the asdf-devel mailing list