Your SlideShare is downloading. ×
0
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Testing ASP.net Web Applications using Ruby

1,638

Published on

Presentation of Testing ASP.net using Ruby I gave at DDD8, January 30th 2010.

Presentation of Testing ASP.net using Ruby I gave at DDD8, January 30th 2010.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,638
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
32
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Testing ASP.net using Ruby<br />Meerkatalyst<br />@Ben_HallBen@BenHall.me.ukBlog.BenHall.me.uk<br />
  • 2. 1| Why you should care2| Object Level testing3| UI level testing<br />
  • 3. What do I mean by Testing ASP.net?<br />
  • 4. Co-Author of <br />Testing ASP.net Web Applications<br />http://www.testingaspnet.com<br />
  • 5. WHY TEST?<br />http://www.flickr.com/photos/atomicpuppy/2132073976/<br />
  • 6. It is 2010. Automated testing is no longer controversial.<br />
  • 7. http://nerddinner.codeplex.com/SourceControl/changeset/view/23425#439968<br />[TestMethod]public void EditAction_Retrieves_Dinner_1_From_Repo_And_Countries_And_Sets_DinnerViewModel() { // Arrangevar controller = CreateDinnersControllerAs(&amp;quot;someuser&amp;quot;); // ActViewResult result = controller.Edit(1) as ViewResult; // AssertDinnerFormViewModel model = result.ViewData.Model as DinnerFormViewModel;Assert.AreEqual(13, model.Countries.Count());}<br />
  • 8. http://nerddinner.codeplex.com/SourceControl/changeset/view/23425#439968<br />[TestMethod]public void EditAction_Retrieves_Dinner_1_From_Repo_And_Countries_And_Sets_DinnerViewModel() { // Arrangevar controller = CreateDinnersControllerAs(&amp;quot;someuser&amp;quot;); // ActViewResultresult = controller.Edit(1) as ViewResult; // AssertDinnerFormViewModel model = result.ViewData.Model as DinnerFormViewModel;Assert.AreEqual(13, model.Countries.Count());}<br />
  • 9. [Fact] public void RsdReturnsValidRsdDoc() {FakeAreaServiceareaService = new FakeAreaService();areaService.StoredAreas.Add(&amp;quot;test&amp;quot;, new Oxite.Models.Area(false, DateTime.MinValue, null, null, Guid.NewGuid(), DateTime.MinValue, &amp;quot;test&amp;quot;));RouteCollection routes = new RouteCollection();routes.Add(&amp;quot;Posts&amp;quot;, new Route(&amp;quot;&amp;quot;, new MvcRouteHandler()));UrlHelper helper = new UrlHelper(new RequestContext(new FakeHttpContext(new Uri(&amp;quot;http://oxite.net/&amp;quot;),&amp;quot;~/&amp;quot;), new RouteData()), routes); Site site = new Site() { Host = new Uri(&amp;quot;http://oxite.net&amp;quot;) };AreaController controller = new AreaController(site, areaService, null, null, null, null, null) { Url = helper };ContentResult result = controller.Rsd(&amp;quot;test&amp;quot;);Assert.NotNull(result);XDocumentrsdDoc = XDocument.Parse(result.Content);XNamespacersdNamespace = &amp;quot;http://archipelago.phrasewise.com/rsd&amp;quot;;XElementrootElement = rsdDoc.Element(rsdNamespace + &amp;quot;rsd&amp;quot;);Assert.NotNull(rootElement);Assert.NotNull(rootElement.Attribute(&amp;quot;version&amp;quot;));Assert.Equal(&amp;quot;1.0&amp;quot;, rootElement.Attribute(&amp;quot;version&amp;quot;).Value);Assert.Equal(&amp;quot;Oxite&amp;quot;, rootElement.Descendants(rsdNamespace + &amp;quot;engineName&amp;quot;).SingleOrDefault().Value);Assert.Equal(&amp;quot;http://oxite.net&amp;quot;, rootElement.Descendants(rsdNamespace + &amp;quot;engineLink&amp;quot;).SingleOrDefault().Value);Assert.Equal(&amp;quot;http://oxite.net/&amp;quot;, rootElement.Descendants(rsdNamespace + &amp;quot;homePageLink&amp;quot;).SingleOrDefault().Value);XElementapisElement = rootElement.Descendants(rsdNamespace + &amp;quot;apis&amp;quot;).SingleOrDefault();Assert.NotNull(apisElement);Assert.Equal(1, apisElement.Elements().Count());XElementapiElement = apisElement.Elements().SingleOrDefault();Assert.NotNull(apiElement);Assert.Equal(rsdNamespace + &amp;quot;api&amp;quot;, apiElement.Name);Assert.Equal(&amp;quot;MetaWeblog&amp;quot;, apiElement.Attribute(&amp;quot;name&amp;quot;).Value);Assert.Equal(areaService.StoredAreas[&amp;quot;test&amp;quot;].ID.ToString(&amp;quot;N&amp;quot;), apiElement.Attribute(&amp;quot;blogID&amp;quot;).Value);Assert.Equal(&amp;quot;true&amp;quot;, apiElement.Attribute(&amp;quot;preferred&amp;quot;).Value);Assert.Equal(&amp;quot;http://oxite.net/MetaWeblog.svc&amp;quot;, apiElement.Attribute(&amp;quot;apiLink&amp;quot;).Value); }<br />http://oxite.codeplex.com/SourceControl/changeset/view/54721#419183<br />
  • 10. [Fact] public void RsdReturnsValidRsdDoc() {FakeAreaServiceareaService = new FakeAreaService();areaService.StoredAreas.Add(&amp;quot;test&amp;quot;, new Oxite.Models.Area(false, DateTime.MinValue, null, null, Guid.NewGuid(), DateTime.MinValue, &amp;quot;test&amp;quot;));RouteCollection routes = new RouteCollection();routes.Add(&amp;quot;Posts&amp;quot;, new Route(&amp;quot;&amp;quot;, new MvcRouteHandler()));UrlHelper helper = new UrlHelper(new RequestContext(new FakeHttpContext(new Uri(&amp;quot;http://oxite.net/&amp;quot;),&amp;quot;~/&amp;quot;), new RouteData()), routes); Site site = new Site() { Host = new Uri(&amp;quot;http://oxite.net&amp;quot;) };AreaController controller = new AreaController(site, areaService, null, null, null, null, null) { Url = helper };ContentResult result = controller.Rsd(&amp;quot;test&amp;quot;);Assert.NotNull(result);XDocumentrsdDoc = XDocument.Parse(result.Content);XNamespacersdNamespace = &amp;quot;http://archipelago.phrasewise.com/rsd&amp;quot;;XElementrootElement = rsdDoc.Element(rsdNamespace + &amp;quot;rsd&amp;quot;);Assert.NotNull(rootElement);Assert.NotNull(rootElement.Attribute(&amp;quot;version&amp;quot;));Assert.Equal(&amp;quot;1.0&amp;quot;, rootElement.Attribute(&amp;quot;version&amp;quot;).Value);Assert.Equal(&amp;quot;Oxite&amp;quot;, rootElement.Descendants(rsdNamespace + &amp;quot;engineName&amp;quot;).SingleOrDefault().Value);Assert.Equal(&amp;quot;http://oxite.net&amp;quot;, rootElement.Descendants(rsdNamespace + &amp;quot;engineLink&amp;quot;).SingleOrDefault().Value);Assert.Equal(&amp;quot;http://oxite.net/&amp;quot;, rootElement.Descendants(rsdNamespace + &amp;quot;homePageLink&amp;quot;).SingleOrDefault().Value);XElementapisElement = rootElement.Descendants(rsdNamespace + &amp;quot;apis&amp;quot;).SingleOrDefault();Assert.NotNull(apisElement);Assert.Equal(1, apisElement.Elements().Count());XElementapiElement = apisElement.Elements().SingleOrDefault();Assert.NotNull(apiElement);Assert.Equal(rsdNamespace + &amp;quot;api&amp;quot;, apiElement.Name);Assert.Equal(&amp;quot;MetaWeblog&amp;quot;, apiElement.Attribute(&amp;quot;name&amp;quot;).Value);Assert.Equal(areaService.StoredAreas[&amp;quot;test&amp;quot;].ID.ToString(&amp;quot;N&amp;quot;), apiElement.Attribute(&amp;quot;blogID&amp;quot;).Value);Assert.Equal(&amp;quot;true&amp;quot;, apiElement.Attribute(&amp;quot;preferred&amp;quot;).Value);Assert.Equal(&amp;quot;http://oxite.net/MetaWeblog.svc&amp;quot;, apiElement.Attribute(&amp;quot;apiLink&amp;quot;).Value); }<br />http://oxite.codeplex.com/SourceControl/changeset/view/54721#419183<br />
  • 11. http://grabbagoft.blogspot.com/2007/09/authoring-stories-with-nbehave-03.html<br />[Story] public void Should_find_customers_by_name_when_name_matches() { Story story = new Story(&amp;quot;List customers by name&amp;quot;); story.AsA(&amp;quot;customer support staff&amp;quot;) .IWant(&amp;quot;to search for customers in a very flexible manner&amp;quot;) .SoThat(&amp;quot;I can find a customer record and provide meaningful support&amp;quot;); CustomerRepository repo = null; Customer customer = null; story.WithScenario(&amp;quot;Find by name&amp;quot;) .Given(&amp;quot;a set of valid customers&amp;quot;, delegate { repo = CreateDummyRepo(); }) .When(&amp;quot;I ask for an existing name&amp;quot;, &amp;quot;Joe Schmoe&amp;quot;, delegate(string name) { customer = repo.FindByName(name); }) .Then(&amp;quot;the correct customer is found and returned&amp;quot;, delegate {Assert.That(customer.Name, Is.EqualTo(&amp;quot;Joe Schmoe&amp;quot;));}); }<br />
  • 12. RECORD AND PLAYBACK<br />http://www.flickr.com/photos/gagilas/2659695352/<br />
  • 13. You can make C# readable<br />But it’s hard<br />
  • 14. http://www.flickr.com/photos/buro9/298994863/<br />RUBY?<br />
  • 15. Natural Language<br />
  • 16.
  • 17. http://www.flickr.com/photos/mag3737/1914076277/<br />
  • 18.
  • 19.
  • 20. RSpec<br />http://www.flickr.com/photos/dodgsun/467076780/<br />
  • 21. Behaviour Driven Development<br />
  • 22. Intent<br />
  • 23. [TestMethod]public void EditAction_Retrieves_Dinner_1_From_Repo_And_Countries_And_Sets_DinnerViewModel() { // Arrangevar controller = CreateDinnersControllerAs(&amp;quot;someuser&amp;quot;); // ActViewResult result = controller.Edit(1) as ViewResult; // AssertDinnerFormViewModel model = result.ViewData.Model as DinnerFormViewModel;Assert.AreEqual(13, model.Countries.Count());}<br />
  • 24. describe<br />
  • 25. describe “when editing”do<br />
  • 26. describe “when editing” do<br /> it<br />end<br />
  • 27. describe “when editing” do<br />it “should return countries where dinners can be hosted”<br />end<br />
  • 28. D:SourceControl erddinner-23425specs&amp;gt;ispecDinnersController_specs.rb<br />*<br />Pending:<br />when editing should return countries where dinners can be hosted (Not Yet Implemented)<br />./DinnersController_specs.rb:2<br />Finished in 0.3511328 seconds<br />1 example, 0 failures, 1 pending<br />
  • 29. describeNerdDinner::Controllers::DinnersController, “when editing”do<br />
  • 30. require ‘NerdDinner.dll’<br />describe NerdDinner::Controllers::DinnersController, “when editing” do<br />
  • 31. $: &amp;lt;&amp;lt; ‘../NerdDinner/bin’<br />require ‘NerdDinner.dll’<br />describe NerdDinner::Controllers::DinnersController, “when editing” do<br />
  • 32. $: &amp;lt;&amp;lt; ‘../NerdDinner/bin’<br />require ‘NerdDinner.dll’<br />Include NerdDinner::Controllers<br />describe DinnersController, “when editing” do<br />
  • 33. it “returns countries where dinners can be hosted” do <br /> controller = DinnersController.new<br />end<br />
  • 34. it “returns countries where dinners can be hosted” do <br /> controller = DinnersController.new(dinner_repos(dinners))<br />end<br />
  • 35. it “returns countries where dinners can be hosted” do <br />controller = DinnersController.new(dinner_repos(dinners))<br /> result = controller.Edit(1).ViewData.Model<br />end<br />
  • 36. it “returns countries where dinners can be hosted” do <br /> controller = DinnersController.new(dinner_repos(dinners))<br /> result = controller.Edit(1).ViewData.Model<br />result.Countries.Count().should == test_data.length<br />end<br />RSpec has really powerful matchers<br />
  • 37. D:SourceControl erddinner-23425specs&amp;gt;ispecDinnersController_specs.rb<br />F<br />1)<br />&amp;apos;NerdDinner::Controllers::DinnersController when editing should return countries where dinners can be hosted&amp;apos; FAILED<br />expected: 13,<br /> got: nil (using ==)<br />./DinnersController_specs.rb:8:<br />Finished in 0.4824219 seconds<br />1 example, 1 failure<br />
  • 38. D:SourceControl erddinner-23425specs&amp;gt;ispecDinnersController_specs.rb<br />.<br />Finished in 0.4355469 seconds<br />1 example, 0 failures<br />
  • 39. require ‘caricature’<br />def dinner_repos(test_data)<br />IDinnerRepository.isolate(:FindUpcomingDinners) {returns test_data} <br />End<br />
  • 40. def create_dinners(count=13)<br /> dinners = []<br />count.timesdo |i|<br /> dinners &amp;lt;&amp;lt; Dinner.new(:country =&amp;gt; “Value#{i}”)<br /> end<br />end<br />
  • 41. describe DinnersController, &amp;quot;when editing&amp;quot; do <br /> let(:dinners) {create_dinners} <br /> let(:controller) {DinnersController.new(dinner_repos dinners)}<br /> it &amp;quot;returns countries where dinners can be hosted&amp;quot; do<br /> result = controller.Edit(dinners.first.id).view_model<br />result.Countries.Count().should == dinners.length<br /> end<br />end<br />
  • 42. result.Countries.Count().should == dinners.length<br />result.Countries.shouldhave_same_count(dinners)<br />module Matchers <br /> class CountEqual<br /> def initialize(expected)<br /> @expected = expected<br /> end<br /> def matches?(actual)<br />actual.Count() == @expected.Count()<br /> end<br /> end<br /> def have_same_count(expected)<br />CountEqual.new(expected)<br /> end<br />end<br />Duck Typing FTW!<br />
  • 43. describe DinnersController, “Managing dinner reservations” do<br /> let(:dinners) { valid_dinners }<br /> let(:controller) {DinnersController.new(dinner_repository dinners)}<br /> describe “when editing“it_should_behave_like “valid dinners” it &amp;quot;returns countries where dinners can be hosted&amp;quot; <br /> end<br /> describe “when saving“ do<br /> describe “the validation for invalid dinners” do<br /> let(:dinners) { bad_dinners(1) }it “should reject a dinner without a name”<br /> it “should reject a dinner without a email address”<br /> it “should accept a dinner if it has a name and email address”<br /> end<br /> describe “confirmation” do <br /> it “should send an email to the organiser once saved”<br /> end<br /> describe “valid dinners” do<br /> it “redirects to thank you page after completing&amp;quot; <br /> end<br /> end<br />end<br />
  • 44. describe &amp;quot;NHibernate&amp;quot; do<br /> before do<br />config = Configuration.new<br /> @cfg = config.configure(File.join(Dir.pwd, &amp;quot;nhibernate.config&amp;quot;))<br /> end<br /> it &amp;quot;can create session factory&amp;quot; do<br />session_factory = @cfg.BuildSessionFactory()<br />session_factory.should_notbe_nil<br /> end<br /> it &amp;quot;can create session&amp;quot; do<br />session_factory = @cfg.BuildSessionFactory()<br /> session = session_factory.open_session<br />session.should_notbe_nil<br /> end<br />end<br />
  • 45. Outside-in Development<br />
  • 46. Cucumber<br />http://www.flickr.com/photos/vizzzual-dot-com/2738586453/<br />
  • 47. Documentation, automated tests and development-aid<br />
  • 48. [Story] public void Should_find_customers_by_name_when_name_matches() { Story story = new Story(&amp;quot;List customers by name&amp;quot;); story.AsA(&amp;quot;customer support staff&amp;quot;) .IWant(&amp;quot;to search for customers in a very flexible manner&amp;quot;) .SoThat(&amp;quot;I can find a customer record and provide meaningful support&amp;quot;); CustomerRepository repo = null; Customer customer = null; story.WithScenario(&amp;quot;Find by name&amp;quot;) .Given(&amp;quot;a set of valid customers&amp;quot;, delegate { repo = CreateDummyRepo(); }) .When(&amp;quot;I ask for an existing name&amp;quot;, &amp;quot;Joe Schmoe&amp;quot;, delegate(string name) { customer = repo.FindByName(name); }) .Then(&amp;quot;the correct customer is found and returned&amp;quot;, delegate {Assert.That(customer.Name, Is.EqualTo(&amp;quot;Joe Schmoe&amp;quot;));}); }<br />
  • 49. Feature: List customers by name As a customer support staff I want to search for customers in a very flexible manner So that I can find a customer record and provide meaningful supportScenario: Find by name Given a set of valid customers When I ask for an existing name Then the correct customer is found and returned<br />
  • 50. Feature: List customers by nameAs a customer support staffI want to search for customers in a very flexible mannerSo that I can find a customer record and provide meaningful supportScenario: Find by name Given a set of valid customersWhen I ask for an existing nameThen the correct customer is found and returned<br />
  • 51. D:SourceControl erddinner-23425features&amp;gt;cucumber list.feature<br />Feature: List customers by name<br /> As a customer support staff<br /> I want to search for customers in a very flexible manner<br /> So that I can find a customer record and provide meaningful support<br /> Scenario: Find by name # list.feature:6<br /> Given a set of valid customers # list.feature:7<br /> When I ask for an existing name # list.feature:8<br /> Then the correct customer is found and returned # list.feature:9<br />1 scenario (1 undefined)<br />3 steps (3 undefined)<br />0m0.020s<br />You can implement step definitions for undefined steps with these snippets:<br />Given /^a set of valid customers$/ do<br /> pending # express the regexp above with the code you wish you had<br />end<br />When /^I ask for an existing name$/ do<br /> pending # express the regexp above with the code you wish you had<br />end<br />Then /^the correct customer is found and returned$/ do<br /> pending # express the regexp above with the code you wish you had<br />end<br />
  • 52. NOT BEST PRACTICE!!<br />Given /^a set of valid customers$/ do @repo = CreateDummyRepo()endWhen /^I ask for an existing name$/ do @customer = @repo.FindByName(&amp;quot;Joe Schmoe&amp;quot;)endThen /^the correct customer is found and returned$/ do @customer.Name.should == &amp;quot;Joe Schmoe“end<br />
  • 53. Given /^customer “([^&amp;quot;]*)” $/ do |name| @repo = CustomerRepository.new(Customer.new(:name =&amp;gt; name)endWhen /^I search for customer “([^&amp;quot;]*)”$/ do |name| @customer = @repo.FindByName(name)endThen /^”([^&amp;quot;]*)” should be found and returned$/ do |name| @customer.Name.should == nameend<br />
  • 54. WebRat<br />http://www.flickr.com/photos/whatwhat/22624256/<br />
  • 55. visit<br />click_link<br />fill_in<br />click_button<br />check and uncheck<br />choose<br />select<br />attach_file<br />
  • 56. EXAMPLES<br />Cucumber, WebRat and Automated UI testing<br />
  • 57. One more thing...<br />
  • 58. Meerkatalyst<br />
  • 59. http://blog.benhall.me.uk/2009/12/sneak-peek-at-meerkatalystlonestar.html<br />
  • 60. http://www.flickr.com/photos/leon_homan/2856628778/<br />
  • 61. Expressing intent<br />
  • 62. Ruby -&amp;gt; C#<br />
  • 63. http://www.flickr.com/photos/philliecasablanca/2456840986/<br />@Ben_HallBen@BenHall.me.ukBlog.BenHall.me.uk<br />
  • 64. using Cuke4Nuke.Framework;<br />usingNUnit.Framework;<br />usingWatiN.Core;<br />namespaceGoogle.StepDefinitions<br />{<br />    publicclassSearchSteps<br />    {<br />        Browser _browser;<br /> [Before]<br />        publicvoidSetUp()<br />        {<br />            _browser = new WatiN.Core.IE();<br />        }<br /> [After]<br />        publicvoidTearDown()<br />        {<br />            if (_browser != null)<br />            {<br />                _browser.Dispose();<br />            }<br />        }<br /> [When(@&amp;quot;^(?:I&amp;apos;m on|I go to) the search page$&amp;quot;)]<br />        publicvoidGoToSearchPage()<br />        {<br />            _browser.GoTo(&amp;quot;http://www.google.com/&amp;quot;);<br />        }<br /> [When(&amp;quot;^I search for &amp;quot;(.*)&amp;quot;$&amp;quot;)]<br />        publicvoidSearchFor(string query)<br />        {<br />            _browser.TextField(Find.ByName(&amp;quot;q&amp;quot;)).TypeText(query);<br />            _browser.Button(Find.ByName(&amp;quot;btnG&amp;quot;)).Click();<br />        }<br /> [Then(&amp;quot;^I should be on the search page$&amp;quot;)]<br />        publicvoidIsOnSearchPage()<br />        {<br />            Assert.That(_browser.Title == &amp;quot;Google&amp;quot;);<br />        }<br /> [Then(&amp;quot;^I should see &amp;quot;(.*)&amp;quot; in the results$&amp;quot;)]<br />        publicvoidResultsContain(stringexpectedResult)<br />        {<br />            Assert.That(_browser.ContainsText(expectedResult));<br />        }<br />    }<br />}<br />
  • 65. Given /^(?:I&amp;apos;m on|I go to) the search page$/ do<br />  visit &amp;apos;http://www.google.com&amp;apos;<br />end<br /> <br />When /^I search for &amp;quot;([^&amp;quot;]*)&amp;quot;$/ do|query|<br />  fill_in &amp;apos;q&amp;apos;, :with =&amp;gt; query<br />  click_button &amp;apos;Google Search&amp;apos;<br />end<br /> <br />Then /^I should be on the search page$/ do<br /> dom.search(&amp;apos;title&amp;apos;).should == &amp;quot;Google&amp;quot;<br />end<br /> <br />Then /^I should see &amp;quot;(.*)&amp;quot; in the results$/ do|text|<br />  response.should contain(text)<br />end<br />
  • 66. Software<br />Recommended:<br />IronRuby<br />Ruby<br />Cucumber<br />Rspec<br />WebRat<br />mechanize<br />Selenium RC<br />selenium-client<br />Caricature<br />activerecord-sqlserver-adapter<br />Optional:<br />XSP Mono<br />JetBrain’sRubyMine<br />JRuby<br />Capybara<br />Celerity<br />Active record <br />active-record-model-generator<br />Faker<br />Guid<br />
  • 67. Useful Links<br />http://www.github.com/BenHall<br />http://blog.benhall.me.uk<br />http://stevehodgkiss.com/2009/11/14/using-activerecord-migrator-standalone-with-sqlite-and-sqlserver-on-windows.html<br />http://www.testingaspnet.com<br />http://<br />http://msdn.microsoft.com/en-us/magazine/dd434651.aspx<br />http://msdn.microsoft.com/en-us/magazine/dd453038.aspx<br />http://www.cukes.info<br />
  • 68. Getting SQL Server to work<br />gem install activerecord-sqlserver-adapter<br />Download dbi-0.2.2.zip <br />Extract dbdADO.rb to rubysite_ruby1.8DBDADO.rb<br />

×