Include file resolution

This is a section you should hopefully never need to read. It explains in detail how implicit 'Procedure' and 'Component' references are resolved during test replay. If you need to read it, your test suite include hierarchy probably is too complicated and you should consider simplifying your includes.

There are basically two scenarios in which QF-Test must implicitly resolve a 'Procedure' or 'Component' reference to another suite when the requested 'Procedure' or 'Component' cannot be found in the current (or explicitly referenced) suite:

  • The current suite includes other suites (by defining them in the 'Include files' attribute of the 'Test suite' root node). In this case, QF-Test searches all included suites in the given order.
  • The current suite (or rather one of its 'Procedures') was called by another suite. Here QF-Test searches the calling suite for the requested node.

The whole thing gets complicated, when (possibly indirect) 'Procedure calls' across test suite boundaries and (possibly indirect, maybe even recursive) includes are combined. Following are detailed explanations of the search algorithm that will hopefully enable you to debug and resolve any include-file related problems.

  • Whenever execution leaves the current suite to continue with some 'Procedure' or to retrieve a 'Component', the other suite becomes the current suite. This process is complemented by two things: the old suite is pushed onto the so-called call-stack and the variable bindings of the new current suite are pushed on top of the fallback bindings stack (see chapter 6), so they override the bindings of the old suite. In the run log this process is documented by adding a Suite-change node which holds all of the run log nodes for the execution that takes place outside the old suite.
  • Any search through test suites starts with the current suite, then continues top-down through the call-stack. So if, for example, A calls B which calls C, then C is searched first, followed by B and finally A.
  • Includes are considered stronger bindings than the call-stack. This means that during the search through the current suite and the suites on the call-stack, at each step the included test suites are searched before moving to the next suite on the call-stack. For example, if A calls B which includes C, A is on the call-stack and B is the current Suite, then B will be searched first, then C, and lastly A.
  • In case of multiple, possibly indirect includes, the search is always conducted depth-first in the oder in which the include files are listed. This means that if A includes B and C, and B includes D, first A is searched, followed by B, then D and then C.
  • If a 'Procedure' is found (possibly indirectly) in an included test suite (as opposed to the current suite, an explicitly referenced suite or a suite on the call-stack), the change from the old current suite to the new current suite doesn't take place in one step. This has to be illustrated with an example right from the start or we'll get totally lost: Let's say A calls B and that A includes C. B calls a 'Procedure' which is found in C by way of A. Instead of changing suites directly from B to C, A will first become the current suite and then C. As a consequence, A gets pushed onto the call-stack again on top of B and its variable bindings are also pushed again on top of B's bindings on the fallback bindings stack. The reasoning behind this is that C, which is now the current suite, is "closer to" A, which includes C, than it is to B, which only happened to be called by A. One could also say that inclusion creates a kind of union, so that to B, A and C will always appear as a single test suite as long as B doesn't call C explicitly.
  • That's it, except for one thing: During a search QF-Test never searches a suite twice. This would be useless in any case, but it is more than an optimization, since it prevents trouble with recursive includes if A includes B and B includes A.

If you really have a problem determining how, why or why not a certain 'Procedure' or 'Component' was retrieved, first take a look at the run log. It shows exactly which suites were used and which variable expansions took place.