cory foy april 29th, 2005 msdn code camp charlotte, nc test driving asp.net development cory foy,...
TRANSCRIPT
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Test Driving ASP.NET Development
Cory Foy, Software EngineerMobileHWY, LLC
[email protected]://www.cornetdesign.com
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Session Timeline
• Agile Manifesto Overview• Test Driven Development Overview• Test First UI Overview• NUnitASP• TFUI with NUnitASP• Mocking ASP.NET Pages• Summary
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Agile Manifesto
• Four Principles– Individuals and Interactions (over
processes and tools)– Working Software (over comprehensive
documentation)– Customer Collaboration (over contract
negotiation)– Responding to change (over following a
plan)
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Extreme Programming
• Automate all manual processes• Do nothing without frequent feedback• Don’t have a bus number of “1”
– Bus Number – Number of people that can be hit by a bus that your project can’t do without
– How to achieve if you are emphasizing Working Software over comprehensive documentation?
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Test Driven Development
• It’s about coding• It’s about design• Way of developing applications by
writing tests• Red-Green-Refactor
– Write a failing test– Make the test pass by doing the simplest
thing– Refactor duplication
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Test Driven Development
• NUnit (http://www.nunit.org)
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Test Driven Development
• Write a test
Watch it fail
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Test Driven Development
• Make the test pass
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Test Driven Development
• Make it right (Refactor)– Pull information from data store
• Have data store be able to be reset to a common baseline
• Tests shouldn’t rely on the results of other tests
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Test First UI
• - Primary work done by Phlip Plumlee• - Principles paper available at
http://industrialxp.org/community/bin/view/Main/TestFirstUserInterfaces
• Why is TDD for UIs naturally hard?– Should be able to write test cases that
force predictable changes in UI– All libraries should submit to program
control– Look and feel problems
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Test First UI
• Reveal()– Phlip’s concept to temporarily show the
form under test for manual inspection when needed.
• Why is TDD for UI Artificially hard?– UIs have steep learning curves for
extending– UI tools designed for drag-n-drop
development, not for complex, robust applications
– UI tools make debugging easy
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Test First UI
• Unique challenges with the web– Server side and Client side code– Different browsers render code
differently– Variety of user agents (desktop, PDA,
mobile)
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• http://nunitasp.sourceforge.net• Extension to NUnit• Originally created by Brian Knowles,
now maintained by Jim Shore• Provides NUnit with the ability to
download, parse and manipulate ASP.NET pages
• Meant for programmers, not QA teams
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• Uses a Browser property for loading web pages and making assertions about various test conditions
• Uses AspTester objects to access properties of the controls, even complex nested or user controls
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• Testable ControlsSystem.Web.UI.WebControls•Button •CheckBox •DataGrid •DropDownList•ImageButton•Label• LinkButton• ListBox• Panel• RadioButton• TextBox •UserControl• ValidationSummary
System.Web.UI.HtmlControls•HtmlAnchor•HtmlInputCheckBox
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• TDD With NUnitAsp– First write failing test
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• Now pass the test
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• With the page created, we want to make sure it is working.
• This means that when a user selects a favorite from the list, the user gets redirected to a different page which retrieves the score for the team.
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• First write a test
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• And make it pass
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• Finally, refactor
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• NUnitAsp Tips http://codebetter.com/blogs/darrell.norton/archive/2004/01/22/5950.aspx
– Test for the URL of the page you expect– Prefer tests for positive visibility – false
can be misleading– Make sure your app works by browsing
to it– Test only critical controls– Long wait – slower than library tests
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
NUnitAsp
• NUnitAsp Drawbacks– Can only assert HttpContxt based
information like Control visibility, Control values, Cookies, etc.
– Certain Control attributes that aren’t sent to the client can’t be tested (DataTextField, DataValueField for DropDownLists
– Session and Cache values can’t be tested directly
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• What are some problems with our current DisplayFavorites.aspx?– Business logic embedded in page– Difficult to test
• NUnitAsp can only test so much• NUnit testing would be extremely difficult
– Code not reusable in other pages
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• How can we solve this?– Use interfaces to permit substitution– Extract business and presentation logic
to a controller / presenter (MVP)http://www.martinfowler.com/eaaDev/ModelViewPresenter.html
– Modify our page to use this controller– Create a mock that can be passed to the
controller for deeper testing
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Building the interface– What are we trying to accomplish?
• Get the favorites for the user• Display the favorites to the user• Let the user select a favorite• Act on the selection action by getting the
current score for the favorite
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Extract the services you want the page to provide out into an interface
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• What is a “mock”?– http://www.mockobjects.com– Objects that pretend to be real objects,
but only contain enough logic to let us run our code
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Why use mock objects?– The real object has nondeterministic behavior– The real object is difficult to set up– The real object has behavior that is difficult to
trigger– The real object is slow– The real object has (or is) a user interface– The test wants to ask the object about how it
was used– The real object does not exist yet
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Why mock ASP.NET pages?– Can dig deep into what actually
happened on the page– Can insert test values into Session and
Cache– Can find out what methods were called,
if callbacks were executed, etc.– GUI Testing is hard
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• How will we use the mocks?– Mock will implement the common
interface– We will pass it into our controller as if it
were our real page– The controller will act on it as if the
mock were the real page– We can inspect the state of fields on the
mock to see what the controller actually did
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Write tests for our mock’s behavior
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Create a mock object that implements our interface
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Extracting Business logic to controller– Model-View-Presenter pattern
• Related to Model-View-Controller• Separates the behavior of a presentation
from the view while allowing the view to receive user events
• Also known as Humble Dialog Box• http://www.martinfowler.com/eaaDev/ModelViewPresenter.html
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Extracting Business logic to controller (cont)– To use MVP, we need to create a
controller capable of interacting with our DisplayFavorites logic
– Controller should accept the IDisplayFavorites interface and perform all business logic and presentation logic through that interface
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Write tests for our controller’s behavior
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Create a controller responsible for accepting the IDisplayFavorites view and acting on it
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Create a controller (continued)
• Note the code here was extracted from our Web page, but now resides in our controller
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
• We will now hook our mock object up to our controller as if it is our ASP.NET page
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Testing our mock object in the controller
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• See if our tests pass
• (Note that our web page test is still passing because we haven’t modified it yet. Always keep the tests green!)
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Modify our web page to implement the interface
• Note that we are raising the FavoriteSelected event when the user clicks the button
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Make sure our tests still pass
• We’ve now refactored our ASP.NET to extract the common functionality to a base class, all while keeping the pages running
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• What have we gained by mocking the page?
• We can now test page members we wouldn’t normally be able to test– Session variables– Control attributes– Method calls
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• What else have we gained?– Since the logic is moved out of the
page, implementing the interface is mostly hooking up the plumbing
– This means that creating pages that make use of this functionality is just a matter of hooking up their plumbing as well
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Creating a Mobile version– Implement the interface
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Mocking ASP.NET Pages
• Wait! Wait, Wait Wait!• Where are the tests?
– NUnitAsp doesn’t currently support testing of Mobile pages
– Work is being done on this – goal to have an extension written by the end of summer to do basic testing of Mobile Controls
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Summary
• Do nothing without frequent feedback• Testing GUIs is hard – but can be
mitigated• Try to make GUI tests (and GUIs) as
thin as possible• Activation Energy – modules that
have tests take less Activation Energy to write more tests
April 29th, 2005 MSDN Code Camp
Charlotte, NCCory Foyhttp://www.cornetdesign.com
Summary
• Further information– http://www.testdriven.com– Yahoo! Groups
• TDD, TFUI, Refactoring
– http://www.nunit.org– http://www.testdriven.net (VS plugin)– http://nunitasp.sourceforge.net– http://www.cornetdesign.com
(presentation)