[MIKE3]
- I think that a <Thread> can still have context (like <TestStep>
for a contained operation ( such
as a PutMessage or GetMessage ).
And since, <Thread> will perform the same operations, an "atomic"
level <Thread> could simply be one that (optionally ) does one single
operation instead of multiple <PutMessage> and <GetMessage>
operations. However, it is an advantage to be able to cluster
<PutMessage> and <GetMessage> operations together in a single
<Thread>, since that is realistically more in line with what a business
transaction is ( i.e. as described in BPSS ). Plus, we keep the context ( CPAId,
ConversationId ) the same for all of those operations.. instead of having to
"pass" that context to the next sibling <TestStep> ( which creates
parameter scoping problems anyway).
So I am in favor of unifying the functionality of a <Thread> and
<TestStep> in to the <Thread> class, and eliminating
<TestStep> entirely.
[Jacques Durand 3] I am all
for getting rid of unneeded constructs. My concern with using "thread"
basically instead of "TestStep" is that it blurrs the thread semantics: now
threads can be nested, without being "forked" (split), and each operation
could be in its own little thread...all that could be confusing. In addition,
a thread cannot pretend to be atomic like a test step was: if we get rid of
test step, the basic building block (the "op") is the atomic unit of
execution.
So far we have succeeded in
keeping "thread chaining" (or composition) simple, aligned with WFlow
practice: a thread only passes control to other threads via branching
operators (split / join, within a conditional or not). A thread is not a bloc
structure, but is a flat sequence of WFlow activities that can spawn other
threads while controlling their concurrency. Can we keep it that
way? So I don't have issue with grouping ops in smaller threads if
needed, as long as we stick to the control ops above (split / join) and avoid
any nesting. I believe so far our use cases don't need more than this.
So I am not sure that we really
need to use "small threads" (one op, or a "clusters"), but if we do, then we
can do as follows (and pass context at the time we "split" (how?)):
<thread name="main"
>
<split> <thread
name="A"/></split>
<join> <thread
name="A"/></join>
<split> <thread
name="B"/></split>
<join> <thread
name="B"/></join>
</thread>
<thread name="A"
>
<put...>
<get
....>
</thread>
<thread name="B"
>
<get...>
<put...>
</thread>
So even if that chaining above
seems a bit heavy, I am not sure it will be needed: I don't see that our Use
Cases require this.
We could still eliminate
TestStep , but only if we really can do without having to use
instead "atomic Threads"...
I think your concern about
contexts (see my next comment later on) can be addressed without need for
"clustering" Ops and
Assertions)
[Jacques
Durand] Again, we need to justify the logic of what is a Test Step. I'd
say it is an atomic unit of execution, but it is NOT a control flow
operator like split, or now Assertion (e.g. cannot branch somewhere
else). Should it include sleep()?
[MIKE2]
- Under our new definition, <TestStep> is no longer an "atomic" level of
execution.. since we can now <Split> Threads from within a
TestStep. This blurs the
distinction between <Thread> and <TestStep>, and raises the
question if we should not simply have <Threads> alone, capable of doing
all the operations of a TestStep.
[Jacques
Durand 2] so again if we take Assertion (or TestAssertion) out of a tset step,
as a standalone control operator for branching or exiting, then we would not
split() in any way from inside a test Step, and Test Step could remain an
atomic unit of execution.
[MIKE3]
- This is true. But branching only at the higher <Thread> level means
you lose the "context" ( i.e. the current <FilterResult> .. the current
ConversationId, CPAId.. and other context of the <TestStep>). That was the original purpose of
<TestStep> .. to provide the low level context to which you refer
previously in this discussion. So
really, one must either keep <TestStep> for the purpose of maintaining context and branching based
upon a <TestAssertion> within a <TestStep>.. or (what I favor)..
eliminating <TestStep>.. and giving a <Thread> all of a
<TestStep>'s properties.
That way, context is always maintained when you <Split> a
<Thread>.
Comments?
[Jacques Durand 3] I favor the
latter too... I think Thread-level is good-enough granularity for context
management, our Use Cases don't need more than that I believe. Also, we
have to keep in mind that now the Assertion, as a conditional operator,
should be able to access the FilterResult of more than one Get operation,
e.g. compare the material from two messages obtained separately within the
same thread. So I think it is not so important to associate Assertion with a
FilterResult (could be the latest one produced in the thread by default), and
generally we'll need to explicitly identify FilterResults, and reference their
ID in Assertion
!