I need help getting started

43 views
Skip to first unread message

KAS

unread,
Aug 4, 2010, 9:28:21 PM8/4/10
to UnitTester
I can't seem to get the hang of using unit testing by first writing my
tests. I am hoping someone will give me some pointers. I am a self
taught 4D programmer so don't have a good background for proper
programming. I am trying to improve my coding with Unit test. It
make sense until I try to do it.

Here is an example of something I want to do.

I have a [Hourly] table of records that has and integer recorded on an
hourly bases. There is the integer field and the Date field.

I want to be able to end up with a total for the Integer field for
each day and create or modify a record in the [Day] table for this
total. Field is the Integer field and the number of the day for the
particular month.

What can I really test for? Integer field not 0, number of day not
within the calendar month.

Hope someone is willing to give this me a little help getting my
finger around how this works.

Ken Spence

Mark Schaake

unread,
Aug 4, 2010, 10:06:26 PM8/4/10
to UnitTester
Hi Ken,

In order to unit test, your code must be designed in a way to
facilitate unit testing. This means that your code must be able to be
executed in isolation (think not dependent on other records or system-
wide configuration settings). For your example (though I'm not sure I
really understand what it is you are trying to accomplish), I would
recommend creating the following "production" methods:

createHourlyRecord(date;intVal)
`Simply creates a record in the [Hourly] table with the passed values.

createUpdateDailyRecord(date)
`Queries the [Daily] table for a record with the given date. If one
does not yet exist, creates a new record, else loads the record READ
WRITE and queries all [Hourly] records of the same date. Then, [Daily]
record updated to hold the sum of the [Hourly]intVal records.

Now you can create some simple unit tests - one for each of the two
methods above. You need to think about how to test the methods. It is
really the same as you would without a unit test. You need to make
sure that after calling the createHourlyRecord method, that a new
record has indeed been created and holds the values you expect. For
this, in your unit test method for the test case method
_createHourlyRecord, you put:

If(Unit_BeginTest("Simple creation test";Current method name))
createHourlyRecord(!01/01/2010!;5)
`Assuming your method leaves the newly created record loaded, you
can make some assertions against it.
`Otherwise, you may need to load the record (via a query) you just
created prior to making the following assertions
Unit_IntegerEqualAssert(5;[Hourly]intValue)
Unit_DateEqualAssert(!01/01/2010!;[Hourly]date)
End if

Then, in your unit test method for the test case method
_createUpdateDailyRecord you need to consider several scenarios. These
may include the following cases (as examples):
1. A [Daily] record does not yet exist for the desired date, and so
should be CREATED
2. A [Daily] record already exists for the desired date, and so should
be UPDATED
3. No [Hourly] records exists for the desired date, so [Daily]sum
should be 0
4. Many [Hourly] records exist for the desired date, so [Daily]sum
should equal the sum of the [Hourly]intVal fields for that date

You may then create a separate test for each of these scenarios within
the test case method _createUpdateDailyRecord:

If(Unit_BeginTest("Daily record does not yet exist, should be
created";Current method name))
C_LONGINT($recordCount_l)
$recordCount_l:=Records in table([Daily])
createUpdateDailyRecord(!01/01/2050!)
Unit_IntegerEqualAssert($recordCount_l+1;Records in
table([Daily]))
End if

... and so on. Another important thing to do is to make sure each test
case method begins with a call to START TRANSACTION and ends with a
call to CANCEL TRANSACTION so that any records created along the way
are automatically discarded.

I hope this helps,

Mark

Mark Schaake

unread,
Aug 4, 2010, 10:10:33 PM8/4/10
to UnitTester
Also, have you watched the screencasts? They may help you understand
the mindset required for test driven development:

http://www.unittester4d.com/screencasts

Mark

On Aug 4, 6:28 pm, KAS <spenc...@me.com> wrote:

Kenneth Spence

unread,
Aug 5, 2010, 10:50:13 AM8/5/10
to unitt...@googlegroups.com
Mark,

Thanks for your response. I think things are clearer.

I think my first mistake is that I am still not breaking my methods up into enough smaller methods.
I also think I have been trying to test all the code in a method when in fact I should only be testing those things that produce a result which in turn should be a method of its own.

Do to lack of training I have always done things from the seat of my pants and just started writing the code. No real planning accept in my head. I have been working with a flowchart lately to try and outline my approach to a problem. I am thinking that what I need to do in the flowchart is write it in a way to shows each of the smaller methods that will be needed to complete the main method and then a chart for each of those methods. From this I am hoping to be able to develop the tests methods.

Not sure it this doesn't just add more work but I do better with pictures.

Does this sound like I am on the right approach?

Ken

> --
> UnitTester: unit testing and test-driven development for 4D.
> www.unittester4d.com
>
> You received this message because you are subscribed to the Google
> Groups "UnitTester" group.
> To post to this group, send email to unitt...@googlegroups.com
> To unsubscribe from this group, send email to
> unittester+...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/unittester?hl=en

Kenneth Spence

unread,
Aug 5, 2010, 9:44:31 PM8/5/10
to unitt...@googlegroups.com
I guess I need a little more clarification on this paragraph.

On Aug 4, 2010, at 8:06 PM, Mark Schaake wrote:

> In order to unit test, your code must be designed in a way to
> facilitate unit testing. This means that your code must be able to be
> executed in isolation (think not dependent on other records or system-
> wide configuration settings).

Are you saying that if an action depends on a record or system setting you can't test it?
Let say I want to do a simple query that needs to use a stored date from a [setting] record.
Are you saying that I would need to first get the [Setting]date and assign it to a variable that then is passed to the Query_Method instead of actually using the [setting]date field in the Query_Method?
The main method that assigns the [setting]date would not be tested but the Query_Method could be. Is this correct?

Thanks,
Ken

Mark Schaake

unread,
Aug 5, 2010, 11:00:55 PM8/5/10
to UnitTester
Hi Ken,

> > In order to unit test, your code must be designed in a way to
> > facilitate unit testing. This means that your code must be able to be
> > executed in isolation (think not dependent on other records or system-
> > wide configuration settings).
>
> Are you saying that if an action depends on a record or system setting you can't test it?
> Let say I want to do a simple query that needs to use a stored date from a [setting] record.  
> Are you saying that I would need to first get the [Setting]date and assign it to a variable that then is passed to the Query_Method instead of actually using the [setting]date field in the Query_Method?
> The main method that assigns the [setting]date would not be tested but the Query_Method could be.  Is this correct?

No, I am not saying that. What I am saying is that you need to setup
your environment in the beginning of a unit test so you don't have to
ASSUME anything. A rule of thumb to follow in unit testing: do not
write tests that rely on some EXTERNAL things - things being records,
settings, whatever. If your method uses a record or two, you should
create those records within the unit test (as opposed to relying on
the existing a record prior to running the unit test). This provides
your unit tests with independence, and allows them to be true "units"
that are self-contained.

Hopefully this makes sense. You can certainly unit test methods that
interact with the database and system settings, however you should
have your tests "setup" the environment (so you don't have to ASSUME
anything). Then, at the end of the test, you should "teardown" your
unit test and restore the environment to its previous state. This is
the reason for the calls to

START TRANSACTION

in the beginning of the test, and

CANCEL TRANSACTION

at the end. If you are relying on files (or other FIXTURES), you will
also need to create those files at the beginning and remove at the end
(or modify and restore).

Hopefully this makes sense.

-Mark

>
> Thanks,
> Ken

Kenneth Spence

unread,
Aug 5, 2010, 11:43:41 PM8/5/10
to unitt...@googlegroups.com
Mark,

Thanks, that does clear thing up.
Hopefully I can get things working properly now.

Ken

Reply all
Reply to author
Forward
0 new messages