From: Water Cooler v2 on
Here's my understanding as of now.

If I were writing a function

bool IsValidContact(Offerer objOfferer, Accepter objAccepter,
TermsAndConditions objTermsAndConditions);


Before writing the function, I'd enlist all the conditions that must be
met for a contract to be valid. Something along the lines of:

1. There must be a valid offer made by an offerer;
2. There must be an unconditional, voluntary acceptance of the offer;
3. The offerer and accepter must be above the age of minority;
4. There must be a valid consideration (quid pro quo).

Though there are many more conditions, for the sake of simplicity, let
us stick to only the above four conditions.

Going from the above four, I'd translate them into code precondition
checks as follows:


1. Assert (objOfferer != null)
2. Assert (objAccepter.Acceptance.IsVoluntary() &&
objAccepter.Acceptance.IsUnconditional())
3. Assert ((objOfferer.Age >= ObjLawOfMinority.MinimumAge) &&
((objAccepter.Age >= ObjLawOfMinority.MinimumAge))
4. Assert (objTermsAndConditions.Consideration.Value > 0)


These four would be the basis of unit tests after writing code.

In the implementation, I'd use Design By Contract (DBC) style
assertion:

if (objOfferer == null)
return false;

if (SomeOtherCondition Not Met)
return false;



Or I might use the straight-forward-one-return-path style design like,


if (objOfferer)
if (SomeOtherCondition Met)
return true;



After writing the implementation of the above function, I'd write unit
test scripts to test each of the above conditions. These would be
seperate functions that would call the function IsValidContract with
invalid and valid values against each of the above four conditions we
outlined.

Now, let me in on some terminology. Which of the above are test cases
and what is the unit tests here?

From: Laurent Bossavit on
> Now, let me in on some terminology. Which of the above are test cases
> and what is the unit tests here?

You are coding a function returning boolean - a predicate.

Your immediate concern is: "how do I know that the function is
correct" ?

A test case is a specification of inputs to and outputs from your
function. If, when supplied these inputs, your function returns
something other than the specified output, then the function is
*incorrect*.

A unit test is code that supplies the inputs, calls the function, and
checks the result against the output specified by the test case.

I think you are confused about preconditions. It is *not* a precondition
on the isValidContract() function that the offerer should be an adult.
Rather, it is the job of the function, when passed a parameter which
denotes a minor, to return FALSE indicating that the contract is not, in
fact, valid.

If I was writing unit tests for this function, I'd probably come up with
something along the following lines:

void testIsValidContract() {
// given these inputs...
offerer = makeMajorOfferer();
acceptance = makeVoluntaryAcceptance();
terms = makeTermsWithValidConsideration();
accepter = makeMinorAccepter(acceptance);
// ...should return false because accepter is a minor
assertFalse( isValid( offerer, acceptance, terms) );
}

(There would be many more such tests, to cover the different cases. How
many tests depends on your approach to test design. The fewer tests you
need to specify for equivalent guarantees of correctness, the better.)

Laurent
From: Water Cooler v2 on

Thanks for your diligent reply, Laurent. It has been very helpful and
interesting.


I think I follow you and believe that my understanding has been correct
so far. What still intrigues me is:

1. What then, are pre-conditions?

My initial assessment showed they were conditions to test inside the
function's implementation, before the function returned valid input. If
they're not that, what are they?


2. I understood the unit-test script you wrote called
testIsValidContract. You tested it for one condition/validation, and as
it concurs with my understanding, you imply that it must extend for all
such validations. Fine. But what about test-cases. You said, they are a
specification of what input the function gets and what it spits out. My
question precisely is, "what is the format in which they are written?"
Could you please produce a list of test-cases for this example we've
taken? That would give me an outline.


Thanks.

From: Daniel T. on
In article <1141051642.754991.221520(a)u72g2000cwu.googlegroups.com>,
"Water Cooler v2" <wtr_clr(a)yahoo.com> wrote:

> Thanks for your diligent reply, Laurent. It has been very helpful and
> interesting.
>
>
> I think I follow you and believe that my understanding has been correct
> so far. What still intrigues me is:
>
> 1. What then, are pre-conditions?
>
> My initial assessment showed they were conditions to test inside the
> function's implementation, before the function returned valid input. If
> they're not that, what are they?

A pre-condition is something about the input such that, if the condition
doesn't hold, the function's result is undefined. In other words, if the
precondition doesn't hold, the function has no way of knowing what to
return. There may be no preconditions in your function.

To put it another way, preconditions are conditions that your function
doesn't have to test, because they must hold *before* the function can
be called.


> 2. I understood the unit-test script you wrote called
> testIsValidContract. You tested it for one condition/validation, and as
> it concurs with my understanding, you imply that it must extend for all
> such validations. Fine. But what about test-cases. You said, they are a
> specification of what input the function gets and what it spits out. My
> question precisely is, "what is the format in which they are written?"
> Could you please produce a list of test-cases for this example we've
> taken? That would give me an outline.

The format for the unit tests depends on the language and test harness
used, but they are written *outside* the function. A test case should
create some input, call the function with that input, then test the
output to see if it is correct.

The tests can also be used by implementers of code that use your
function as examples of proper use.


--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
From: Laurent Bossavit on
> My initial assessment showed they were conditions to test inside the
> function's implementation, before the function returned valid input.

That's right, as long as you're careful with the implications of that
definition. Preconditions are conditions that must prevail for the
function to have a meaningful result. If preconditions are not met upon
entry, that means someone is using the function wrongly. In other words,
someone wrote a bug, and the bug isn't inside the function.

A major benefit of DbC in my opinion is that it makes it easier, in just
that way, to reason about "where the bug is". A precondition violation
implies a bug in the caller; a postcondition violation imples a bug in
the function called.

Thus,
objOfferer != null
is a precondition. It is incorrect to call the function with a null
offerer.

However,
objTermsAndConditions.Consideration.Value > 0
cannot be a precondition, since you *expect* that the function will
sometimes be called with terms that do not comply with this criterion.
The point of writing the function is that it should tell you when that
is the case, by returning FALSE.

> But what about test-cases. You said, they are a
> specification of what input the function gets and what it spits out. My
> question precisely is, "what is the format in which they are written?"

It depends. :)

I'm a practitioner of Test-Driven Development. I write down test cases
in the format of unit tests.

So, the testIsValidContract function I sketched is both things:
- a test case (it specifies inputs and outputs)
- an executable unit test

You can also write down test cases in some other format. On paper, or on
the whiteboard (I do that on occasion), in Excel tables... The precise
format depends on what it is you're coding.

Laurent
 |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9 10 11
Prev: Teaching OO
Next: multimethod + multiple inheritance