Re: [TFUI] The TFUI Principles

yahoogroups-1e+8sjoZAN9Wk0Htik3J/[email protected]
Newsgroups gmane.comp.programming.test-first-user-interfaces
Message-ID <[email protected]>
Hi Phlip,
Glad to see you're back!

A couple of weeks ago I came up with an
interesting insight. If you drive the UI with
FIT, and relentlessly remove all duplication
from both the FIT tests and the GUI, then
you ought to get the separation of
function that everyone has been advocating
for years.

Comments?

John Roth


----- Original Message ----- 
From: "Phlip" <phlip2005.at.gmail.com-hHKSG33Tihg+1LFaA5+Ji38/[email protected]>
To: "[email protected]" 
<testfirstuserinterfaces.at.yahoogroups.com-hHKSG33Tihg+1LFaA5+Ji38/[email protected]>
Sent: Saturday, February 05, 2005 10:10 PM
Subject: [TFUI] The TFUI Principles


>
> Gang:
>
> I have returned to my perennial essay (after a sabatical applying
> Broadband Feedback to a crunch-mode situation...).
>
> The TFUI Principles
> GUIs and GUI testing provide a roadbump to those learning Test Driven
> Development. Given a difficult combination of experience, tools, and
> goals, folks meet with common problems and mistakes. This essay
> addresses the problems and issues GUIs generate, and constructs a
> strategy that ports to any GUI situation.
>
> What is Test Driven Development?
> Briefly, write failing tests, write code to pass them, and then
> refactor the code to improve its design. After the fewest possible
> edits - say ten at the most - run all the tests, and predict their
> results. This technique makes the odds of bugs and the odds of excess
> refactoring very low.
>
> Why Test FIRST?
> Why wash your hands before performing surgery? TDD is a good habit
> that trades long hours debugging for short minutes writing new test
> cases. Prevention is better than a cure. If tests unexpectedly fail,
> passing tests should only be an Undo away.
>
> Why is TDD for GUIs naturally hard?
> The target situation this: We should be able to write new test cases
> that force /predictable/ changes in a GUI's appearance and response.
> All other libraries submit to program control, making prediction easy.
> But GUIs have a side that only users can see or touch.
>
> We will address this problem by enabling test cases that temporarily
> present GUIs, under test, for inspection and interaction. This, in
> turn, allows us to grow extra test code - test fixtures - to increase
> the odds that we can predict GUI changes.
>
> Why is TDD for GUIs artificially hard?
> GUI Toolkits have steep learning curves. This inspires toolkit vendors
> to compete to bundle suites of helper applications - wizards, form
> painters, debuggers, etc. - with their GUIs. A good GUI tool can
> flatten a GUI Toolkit's learning curve.
>
> So the GUI Layer, within a large project, may suffer neglect from much
> of a team's total experience. Because the backend of a project - the
> Logic Layer - is mysterious, complex, and valuable, it often receives
> more senior attention, and more careful development practices. When
> leaders think that GUI development is "easy", they might not pay so
> much attention to the growth of its design.
>
> To put it bluntly, senior developers carefully write Logic Layers, and
> associate developers paint and debug GUIs.
>
> GUI Toolkit vendors reinforce this culture. Their marketeers claim,
> "Anyone can write simple forms with our system!" The fun starts when a
> team attempts to scale these simple forms up to complex and
> well-balanced applications. While most of the Logic Layers in our
> industry suffer from the bad effects of Waterfall, GUI development
> labors in the salt mines of Code-and-Fix. Then GUI Toolkit vendors
> reinforce the situation by providing elaborate and tempting wizards
> and debuggers, to help you write code you don't understand, and then
> to help you debug it until it works.
>
> How to avoid TDDing a GUI?
> The first line of defense, in any Agile project, is to avoid fixing a
> potential problem until it can be successfully forced to the surface.
> Engineers try to cause the next problem they intend to solve. If they
> can't cause the problem, they are finished.
>
> For GUIs, this strategy leads to the idea that as much of a GUI's
> logic as possible should be written in a separate module, decoupled
> from the GUI. We will observe this decoupling by following a very
> simple rule, with a name. The part of an application that is shaped
> like the GUI, but is decoupled from it, is the "Representation Layer".
> This term corresponds to terms in other papers such as "Logical User
> Interface" or "Presentation Layer". We use our Representation Layer to
> convert one format to another - the Logic Layer's format to the format
> the user experiences. However, we can easily distinguish our
> Representation Layer by applying a very simple and important rule:
>
> A Representation Layer may not use any identifier from the GUI Toolkit.
>
> If your GUI Toolkit provides, say, "Label", "Form", and "Pushbutton"
> identifiers, your Representation Layer must not use any of them. This
> technique exposes your Representation Layer to the full benefit of
> logical design techniques, such as TDD, without the encumbrance of GUI
> testing.
>
> Anything the user can do to a GUI, a programmer can do, the same way,
> to a Representation Layer. If the user can scroll a list box and
> select a name, then a programmer could write statements that fetch a
> list of names with a method, and could select the index of one name
> with another method. The Logic Layer may or may not keep any names in
> any list; the Representation Layer re-arranges data to satisfy user
> needs.
>
> Anything the GUI can do to a user, the Representation Layer must do to
> a programmer. If selecting an item from ListBoxA repopulates ListBoxB,
> then the Representation Layer provides a callback or an Observer
> Pattern event to trigger this repopulation.
>
> When the GUI Layer is very thin, it becomes humble. It only delegates
> all responsibilities directly to the next layer.
>
> Why bother TDDing the GUI?
> Why do we insist on doing the impossible? No matter how thin you think
> your GUI Layer is, and how much logic you push out into the
> Representation Layer, the simple fact is that bugs spontaneously
> generate in code without tests. TDD will illustrate this effect by
> pushing the defect rate down, allowing the testless parts of your
> program to stick out like sore thumbs.
>
> Many GUIs, including mine, will grow and live happy lives without
> tests. We could easily follow a policy of "Ain't broke don't fix it."
> We could decide not to write tests in for some of our modules, until
> we need to. We could decide to "capture bugs with tests", and only
> write tests after we detect bugs. So by attempting to follow the Agile
> aphorism "You Aren't Gonna Need It", we might defer labor hoping to
> permanently avoid it.
>
> That strategy has one major flaw, called "activation energy". If a
> module already has tests, new tests are very easy to write. The
> activation energy is low. However, modules without tests make new ones
> very hard to write. (Hence books on the subject, such as /Working
> Effectively with Legacy Code/ by Mike Feathers.) The activation energy
> is much higher.
>
> When you receive a defect report, the energy required to "just fix it"
> is usually lower than the energy required to retrofit tests, capture
> the bug with test(s), and /then/ kill it. So each time you "just fix
> it", and put off the labor, the next time gets easier. And more
> likely.
>
> Tests are the only aspect of Agile development that you /are/ going to 
> need.
>
> All new modules, including GUIs, must start with tests. That's the
> only way to ensure that test rigs grow, with their modules, and remain
> ready to assist in all advanced development.
>
> How to TDD a GUI?
> Wizards, form painters, and debuggers are useful tools. We start TFUI
> by making sure our lowly test cases can compete with them. We need to
> spend more time among our test cases than among our vendor's tools'
> GUIs, or our target application's GUI.
>
> That requires giving our test cases a GUI of their own.
>
> To get there efficiently, without spawning a new corporate division,
> we will grow this GUI only by responding to real problems in our
> project. This system works by giving names to solutions for those
> problems, and ensuring the solutions reinforce each other.
>
> If you use an off-the-shelf GUI test system, you can easily lead it
> towards this system. However, even the most limited GUI Toolkits can
> grow this system from their primitive components.
>
> One Test Button
> To test, keep your hands on the keyboard or mouse, and tap one
> function key or button. The button invokes a test rig to save all
> changed files, run selected tests, and report the results back, as
> fast as possible, and with no further interaction.
>
> This principle generates all the other principles. They are all
> reactions to common reasons we might need to perform any other
> interaction at test time.
>
> Just Another Library
> When you learn a GUI Toolkit by learning to use its form painter, you
> may begin to think in terms of "GUI on the outside, source code on the
> inside". To learn to take control of windows and forms /as objects/,
> we set a very simple goal:
>
> During a test run, permit the fewest possible obnoxious side effects.
> Run as many test cases as possible without displaying windows.
>
> That's just a goal; it's not a rule. Trying to achieve the goal
> generates many useful side-effects. Most windows can react to display
> commands without displaying their results on your desktop. When you
> harness that effect, your tests will run quick and quiet. And that, in
> turn, leads to less hesitation before hitting the One Test Button.
>
> Regulate the Event Queue
> To take control of a window, under test, you must learn how its event
> queue dispatches messages. Some messages you must throttle -
> especially the paint messages. And some messages you must let thru,
> such a test case's messages that simulate user input.
>
> Control over those aspects provides enough tools for us to start
> giving our test cases a GUI. Write a function called 'reveal()', and
> temporarily call it from test cases.
>
> Temporary Visual Inspections
> Turn on the Event Queue, during a test case, to visually inspect its
> window populated by test data. The test run shall block until the
> window closes, then subsequent tests shall run.
>
> Temporary Interactive Tests
> While the GUI displays, use it to manually research GUI Toolkit behavior.
>
> Those two practices provide our test case's GUI. The reveal() fixture
> displays our testee window, populated with test data. That allows us
> to spot-check our test case, and make. Then we comment out the
> reveal() call, and ensure the test code works without visual
> inspections.
>
> And the ability to temporarily reveal() leads to a convenient platform
> to record images of windows under test.
>
> Broadband Feedback
> GUIs can record animations of activities during tests. Acceptance Test
> Frameworks can command test cases to record a gallery of results.
>
> The previous 6 Principles force the review of GUI appearance and
> behavior into the tests, away from the wizards, form painters, and
> finished application. They allow us to take control of the situation,
> and prevent the need to excessively manually test.
>
> Now we leverage those Principles to develop test fixtures (test-side
> reusable methods) that enable predictable changes.
>
> Query Visual Appearance
> GUI Toolkits provide the ability to query what they would look like if
> you could see them. All such queries are simulations. Tests must learn
> how to query that a GUI correctly obeyed the commands from its GUI
> Layer code.
> o Tests on Controls may Get details which Production code Set.
> o Tests on Scripts parse the script, looking for details.
> o Tests on Paint() events use Mock Graphics objects to generate a Log 
> String.
>
> Simulate User Input
> Test cases simulate events and check responses.
> o Loose User Simulations
> Call the same method as an event handler would have called.
> o Firm User Simulations
> Find the handler bound to an event and call it.
> o Strict User Simulations
> Push a raw input event into the event queue.
>
> Fault Navigation
> After a test run, the engineer can tell if a compile fails, or a test
> fails, or the code faults, without pressing any other button besides
> the One Testing Button. After a failure, the engineer optionally
> automatically navigate to the failing line.
>
> Flow
> During tests, the editor remains available, activated, and unblocked.
>
> GUI development depends on focussing on those problems early, and
> finding solutions for the intersection of your GUI Toolkit and your
> target application.
>
> Many of those ideas seem obvious. However, for every GUI project that
> spontaneously solved them, there is another that missed a few. The
> idea that your editor should remain unblocked during a test run might
> seem impossible to programmers familiar with, say, Visual Basic 6.
>
> Put together, the strategy seems to resemble a paradox. To avoid
> manually reviewing GUIs, you must write a reveal() method that
> manually, temporarily reveals a GUI, under test. This is not a
> paradox; it is taking control of the situation. Wizards, form
> painters, and debuggers no longer control us. We control when and how
> to manually review our GUIs. When test cases temporarily present GUIs
> in their exact tested state, differences between those GUIs and the
> test assertions' opinions become easy to fix.
>
> ----
>
> The remaining verbiage consists of simple but very powerful projects
> grown from scratch using these principles.
>
> -- 
>  Phlip
>
>
> To unsubscribe, email:
> TestFirstUserInterfaces-unsubscribe-hHKSG33TihhbjbujkaE4pw@public.gmane.org
>
> Yahoo! Groups Links
>
>
>
>
>
>
>
> 



To unsubscribe, email:
TestFirstUserInterfaces-unsubscribe-hHKSG33TihhbjbujkaE4pw@public.gmane.org
 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/TestFirstUserInterfaces/

<*> To unsubscribe from this group, send an email to:
    TestFirstUserInterfaces-unsubscribe-hHKSG33TihhbjbujkaE4pw@public.gmane.org

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.