#- Copyright (c) 2008-2020 James Grenning --- All rights reserved
#- For exclusive use by participants in
#- Wingman Software training courses.
#- Cannot be used by attendees to train others without
#- written permission.
#- www.wingman-sw.com james@wingman-sw.com

------------------------------------------------------------
NOTE
As you complete a part of the exercise, it is helpful
to delete the completed part's text from this instructions
file.
------------------------------------------------------------

Current Situation
-----------------
The CEO is due here any minute for a demo. He may bring
the new hardware fresh from the vendor.  We want to have
working cleac code covered by tests.  The CEO is an
ex-programmer and knows clean code and the value of tests.
We need to show working code, not throw away prototypes.
Keep focused on adding new functionality test by test.

General Instructions
--------------------
Please do not change non-highlighted files
 -- let my know if you think you have to.

------------------------------------------------------------
Part-3 Refactor your tests
------------------------------------------------------------

Objectives
----------
Duplication in tests makes for a lot of clutter, obscuring
what is being done.  Refactoring at the first whiff of a
problem make life easier.  See how clean tests are easier
to understand.

Practice refactoring your tests and keeping them running the
whole time.

See how helper functions can be added to a test group to allow
you to create your own domain specific testing language.

Instructions
------------
Refactor your tests so that each test is more concise, clearly showing
what is being tested, and the expected behavior. Extract common code
into helper functions inside the test group. If you are not sure how
test group helper functions work, ask your instructor.

Work incrementally so that your tests always pass.

Helper functions should be defined in the test group that improve
readability and reduce duplication.

Suggested helper functions:
    TransitionClockTo(day, minute) - test group member
            sets the fake time and wakes up
    THEN_NO_LIGHTS_CHANGED - use a macro for better feedback
    THEN_LIGHT_IS_ON(id)
    THEN_LIGHT_IS_OFF(id)

-- After you finish this exercise, let me know and continue --

------------------------------------------------------------
Part-4 Evolve core behavior
------------------------------------------------------------

Objectives
----------
Test-drive core behavior of a module using link time test stubs
for collaborating modules.

Current Situation
-----------------
In the previous exercises, you should have test-driven a
skeleton of the LightScheduler and cleaned up your tests.
You should be turning on a single light. Resist
adding things to the design until the tests call for it.
No collections should be added until more that one event
is called for in the tests. No boundary checks should be
done until the test set's up the situation where the
boundary check is needed.

Test-drive the time and day matching functionality. You
can get all this working using only a single event. You
can paste this test list into your test file and work
your way through them. Some of the test list items may
turn into multiple TEST cases.
    a) A light scheduled to turn off
    b) Light scheduled for a specific day does not change on
         the wrong day.
    c) Light scheduled for a specific day does change on the
         right day.
    d) Schedule a light to react EVERYDAY
    e) Remove a scheduled turn on event, when the scheduled
        time occurs, the previously scheduled light does not turn on
    f) Schedule a light to react on WEEKDAYs
    g) Schedule a light to react on WEEKEND days

Ask for help if you need it.  Share the keyboard.

-- After you finish this exercise, let me know. --
-- Don't continue until we talk. --

------------------------------------------------------------
Part-5 Generalize for multiple events
------------------------------------------------------------

Objectives
----------
Experience having a test safety net in place while you make
a rather large change to the system's behavior.

Practice keeping test passing with every change.

Experience the 'N' part of the 0,1,N pattern.

See how far a simple stub got you, and how evolving it did
not result in major rework because your tests were clean.

Current Situation
-----------------
The CEO is due here any minute for a demo, you are ready, but
have more work to do for multiple event handling.  It is
imperative that you can demo the single light system. You
can keep working, but you must keep the tests passing.

In the previous exercise, you should have test-driven EVERYDAY and
specific day matching logic for the light scheduler.  Now we will
go after the next challenge: making the design work for its
design limits (128 scheduled events, and 32 lights).

Design Evolution Approach
-------------------------
To help you keep test passing, leave the single event
code in place and add the multiple even code next to it.

You can make a few changes to your code to make the transition
to N events easier.  Refactor your code so that multiple
will fit better. Maybe in your wake up function you can
extract a helper function that that could be called in a loop.

Incrementally add the multiple event code next to the
single event code.  Once you think you are done. Enable the
first multiple event test in 5.1.  If it passes, carefully
remove the single event code.

Exercise Steps
--------------
5.1) Write a test that turns on a light, then later the same day
     turns it off.  See it fail. Put the test into
     IGNORE_TEST mode so you can get ready for multiple events
     without the failing test in your face.

5.2) Convert the design so it handles multiple events, leaving
     single event passing its test at all times

5.3) Enable the ignored test, see it pass.

5.4) Remove any duplication left behind during the refactoring.

5.5) Schedule two lights to react at the same time.  You will
     need to make your spy smarter to pass this test.

-- After you finish this exercise, let me know. --

------------------------------------------------------------
Part-6 Boundary Conditions and special cases
------------------------------------------------------------

Exercise Steps
--------------
6.1) Test design constraints
    a) Scheduler rejects light IDs that are out of the
       allowed range
    b) Scheduler rejects new schedules when the maximum number
       of scheduled events is exceeded.
    c) Scheduler rejects multiple events for the same id,
       minute and day.
    d) Allow setting a fire-once attribute to a
       scheduled event.
    e) Write a test to assure that triggering an event
       does not delte it, unless it is a fire-once event

6.3) Are there other tests you need?  Add them.

Ask for help if you need it.  Share the keyboard.

-- After you finish this exercise, let me know.  --
-- Continue with the next exercise --

------------------------------------------------------------
Part-7 Time service callback
------------------------------------------------------------

Objectives
----------
Test-drive wiring in the callback.  Recognize when a
test group needs to be split due to unneeded setup.

Exercise
-----------------

The LightScheduler should register with the TimeService
for its wake up call.
    a) Make sure the scheduler registers during Create
      * You'll need to test-drive some more behavior into your
        FakeTimeService
    b) Make sure the scheduler removes its registration
       in Destroy
      * You'll need to test-drive some more behavior into your
        FakeTimeService
    c) These tests should be in their own test group,
       though they can be in the same file.
    d) Add a function to your FakeTimeService to simulate
       a one minute tic, and use it where you used to call
       WakeUp directly



Ask for help if you need it.  Share the keyboard.

-- After you finish this exercise, let me know. Continue --

------------------------------------------------------------
Part-8 Add more meat to the bones
------------------------------------------------------------

Objectives
----------
Get more practice at writing tests and incrementally building the
implementation.

Continue to add feature one slice at a time.

Practice designing good test cases from a vague couple
bullet points.

Current Situation
-----------------
We have a few more scheduler features that are needed. By now, you
probably know what to do.

Here are the remaining features

    a) Randomize light reaction by +/- 30 minutes
      * You'll need to test-drive a RandomMinuteGenerator.
      * You'll need a FakeRandomMinuteGenerator.
    b) EVERYDAY schedule can have specific days overridden.

Requirements refinement
    c) The fine print of the UI agreement says lights
       are numbered 1-32. The hardware wants 0 to 31.
    d) Weekend schedule should start at 6PM on FRIDAY.

Ask for help if you need it.  Share the keyboard.

-- After you finish this exercise, show me your work.  --
