

#- 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 is an 
ex-programmer and knows clean code and the value of tests.
He wants to see working code, not throw away prototypes.
Keep focused on adding new functionality test by test.

------------------------------------------------------------
Part-1 Spies and Fakes
------------------------------------------------------------

Objectives
----------
To create a spy for the LightController.

To practice test-driving and working in small steps.

To practice creating tests as documentation.

Exercise
--------
We are going to test drive the LightController interface and spy implementation.

The LightControllerSpy implements a spy version of the 
LightController interface functions.  The spy also has 
a few extra functions to access the intelligence 
collected by the spy.  You can find the interface function
declarations in the design discussion in the notes.
        
    The LightController's interface needs to support 
    functions to turn on and off lights. Light states 
    cannot be queried through the LightController.
            
    Write tests for the LightControllerSpy that documents 
    its behavior.
        - The spy lights are initialized. 
        - The test can read the ID of the last light 
          controlled.
        - The test can read if the last control was to 
          turn on or off a light.
          
    The course notes provide an example of the 
    LightControlerSpy and its tests.

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

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

------------------------------------------------------------
Part-2 Design and Wiring
------------------------------------------------------------
2) Review the first few FakeTimeService tests about setting
fake day and minute.  You will use them in the next part.


Exercise Objectives
-------------------
- Practice TDD, working in small verifiable steps 
  and skillfully procrastinating.
- Practice not writing untested code.
- Test-drive the interface for LightScheduler.
- Test-drive a skeleton of the design using link 
  time test stubs.
- Use an OS abstraction layer to break dependencies 
  on the embedded operating system.
- Use a hardware abstraction layer to break dependencies 
   on the hardware.
- Try your design ideas with a thin slice through the design.


Design Ideas
------------
You've thought of how you will build the LightScheduler. 
Discuss with your partner.
- How will you store each scheduled item?
- When will you interact with the TimeService and 
  LightController? 

Refer to the course notes for Light Scheduling 
Requirements, design and test fixture.

Resist putting in code until the test calls for it.  
For example, do not add any collection (array) 
to hold the multiple events until there is a test that 
schedules more than one light control event (part 5 of the 
exercise)

Exercise Steps
--------------
Test-drive the skeleton of the LightScheduler. 
The course notes provide examples.

The first three tests lead you to define the interface 
of the LightScheduler.  The fourth test confirms that 
your design idea works and is testable. It may seem like 
nothing is being tested. That's OK. The tests are guiding 
us through getting key interfaces compiled and linked. 
Implement these tests
    a) At startup the no lights are operated, nothing 
       is scheduled.
    b) If there are no scheduled light controls, when 
       the Wakeup() callback happens no lights are controlled.
    c) A light scheduled to turn on, does not turn on at 
       the wrong time.
    d) A light scheduled to turn on everyday, turns on at
       the right time.

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

After you finish this part of the exercise, you have proven the concept! 
You have a thin slice of functionality, proving the design and test approach. 
You should not have an array or collection of scheduled events. If you do, 
take it out and use just one.

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

------------------------------------------------------------
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)

What is the best place to put the light checking macros?  
Put them there.
    
------------------------------------------------------------
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 turn on on 
         the wrong day.
    c) Light scheduled for a specific day does turn on on the  
         right day.
    d) Remove a scheduled turn on event, when the scheduled 
        time occurs, the previously scheduled light does not turn on

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.

5.6) Now add weekend and weekday support.  Show me your tests 
     when you finish.

------------------------------------------------------------
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
    b) Make sure the scheduler removes its registration 
       in Destroy
    c) These tests should be in their own test group,  
       though they can be in the same file.
        

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) Schedule for weekends.
    b) Schedule for weekdays.
    c) EVERYDAY schedule can have specific days overridden.
        warn the user when there is an override
        
Requirements refinement
    d) The fine print of the UI agreement says lights 
       are numbered 1-32. The hardware wants 0 to 31.

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

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