SlideShare a Scribd company logo
1 of 79
Testing C# and ASP.net using Ruby Meerkatalyst @Ben_HallBen@BenHall.me.ukBlog.BenHall.me.uk
London based C# MVPWeb Developer @ 7digital.com Working on a number of Open Source Projects Co-Author of  Testing ASP.net Web Applications http://www.testingaspnet.com
How we can apply Ruby testing techniques to C#	- In mindset	- In practice 1|	Object Level testing2|	Systems testing
WHY? http://www.flickr.com/photos/atomicpuppy/2132073976/
VALUE
Realised Ruby doesn’t have as many problems as .net
Natural Language
Test Driven Development TDD
I love writing tests upfront
Not sure about implementation According to various TDD books blogs
Help with an initial design but what about long term?
“Unit”
Behaviour Driven Development BDD
Shift focus Final Intent
Code Coverage
Context Specification
RSpec http://www.flickr.com/photos/dodgsun/467076780/
Ruby (via IronRuby) p = ProductController.new(nil) C# public class ProductController : Controller { IStoreService _service;    public ProductController(IStoreService service)    {       _service = service;    } } Thanks to TekPub for Kona sample
Define the context C# public ActionResult Index(int? id) { ProductListViewModel model = null;    if (id.HasValue)       model = _service.GetHomeModel(id.Value);    else       return RedirectToAction("Index", "Home");       return View(model); } Ruby (via IronRuby) describe ProductController, “Product homepage requested" do   context "when Category ID is empty" do   end end Thanks to TekPub for Kona sample
Create the context $: << ‘../../Kona/bin/’ require ‘Kona.dll’ Include Kona::Controllers describe ProductController, “Product homepage requested" do   context "when Category ID is empty" do   end end Thanks to TekPub for Kona sample
Create the context require '../spec_helper‘ describe ProductController, “Product homepage requested" do   context "when Category ID is empty" do   end end Thanks to TekPub for Kona sample
Create the context require '../spec_helper‘ describe ProductController, “Product homepage requested" do   context "when Category ID is empty" do      before(:each) do         controller = ProductController.new nil category_id = nil         @result = controller.Indexcategory_id      end   end end Thanks to TekPub for Kona sample
Define the spec require '../spec_helper‘ describe ProductController, “Product homepage requested" do   context “with empty Category ID" do      before(:each) do ... End     it "should redirect to main landing page" do          @result.route_values[‘controller'].should == ‘Index’ 	  @result.route_values[‘home'].should == ‘Home’     end end Thanks to TekPub for Kona sample
Stubbing via caricature context “with validCategory ID" do    Before(:each) view_model = product_list('Test Category')        service = isolate Services::IStoreService service.when_receiving(:get_home_model).with(valid_category_id).return(view_model)        controller = ProductController.new service        @result = controller.Indexvalid_category_id    end    it “returns a view model” do       @result.view_model.should_not == nil    end    it “should return name of selected category” do       @result.view_model.selected_category.name.should == 'Test Category‘    end end Thanks to TekPub for Kona sample
Tests and Databases describe Services::StoreService do   before(:all) do session = NHibernate::create_session NHibernate::insert_category session     Services::StoreService.new session     @model = service.get_home_model 0   end   it "should return constructed object" do     @model.should_notbe_nil   end   it "should return all categories from database" do     @model.Categories.to_a.Count.should == 1   end end Thanks to TekPub for Kona sample
http://www.flickr.com/photos/buro9/298994863/ WHY RUBY?
[Subject(typeof(HomeController))]public class when_the_navigation_controller_is_asked_for_the_header :           specification_for_navigation_controller{        static ActionResult result;        Establish context = () => identity_tasks.Stub(i => i.IsSignedIn()).Return(true);        Because of = () => result = subject.Menu();        It should_ask_the_identity_tasks_if_the_user_is_signed_in = () => identity_tasks.AssertWasCalled(x => x.IsSignedIn());        It should_return_the_default_view = () => result.ShouldBeAView().And().ViewName.ShouldBeEmpty();        It should_not_use_a_master_page = () => result.ShouldBeAView().And().MasterName.ShouldBeEmpty();        It should_set_the_view_model_property_to_a_new_menu_view_model = () =>result.Model<MenuViewModel>().ShouldNotBeNull();        It should_set_the_properties_of_the_view_model_correctly = () => result.Model<MenuViewModel>().IsLoggedIn.ShouldBeTrue();    }
describe HomeController, “When the navigation controller is asked for the header” do   before(:all) do       @identity_tasks.Stub(i => i.IsSignedIn()).Return(true);       @result = subject.Menu();    end   it “should ask the identity tasks if the user is signed in” do       @identity_tasks.did_receive(:is_signed_in) .should be_successful   end   it “should return the default view” do     @result.shouldbe_view     @result.view_name.shouldbe_empty   end   it “should not use a master page” do     @result.shouldbe_view     @result.master_name.shouldbe_empty   end  it “should set the view model property to a new menu view model” do     @result.shouldbe_view    @result.model.should_notbe_nil  end  it “should set the properties of the view model correctly” do     @result.model.is_logged_in.shouldbe_true  endend
Consider your test suite containing > 500 tests Each test matters. But each problem hurts more
Share specs share_examples_for "unauthorized user" do    it 'sets an-error message' do result.view_model.error_message.should == "Sorry, you need to login to access."    end    it 'redirects to the login page' do result.view_name.should   end end describe CheckoutController do it_should_behave_like “unauthorized user“describe AccountController doit_should_behave_like “unauthorized user“
Include   additional functionality require ‘nhibernate_helpers’require ‘product_creation_extensions’require  ‘customer_creation_extensions’describe ProductController do
model.Categories.to_a.Count.should == 1 model.Categories.should have(1) module Matchers     class CountCheck     def initialize(expected)       @expected = expected     end     def matches?(actual) actual.to_a.Count() == @expected     end   end   def have(expected) CountCheck.new(expected)   end end Duck Typing FTW!
Dynamically create specs def find_products(category)Product.Find(:all, :conditions=> “category #{category}”)enddescribe ‘products should be able to be added to basket' do    before(:all) do     @basket = Basket.new  endfind_products(‘Boots’).each do |p|    it “can add #{p.product_name} to basket" do      @basket.add_item p.id      @basket.should contain(p)     end  endend
INTEGRATION TESTS http://www.flickr.com/photos/gagilas/2659695352/
I’m against integration tests Or at least 90% of them
Multiple Collaborators
Unmanageable nightmare
12 hour execution time?
5174 passed, 491 failed, 94 skipped
“Tests aren’t failing because of defects”
‘Nearly’ end-to-end While knowing about everything in the middle...
Becomes a pain to refactor
FEAR
FEAR
UNIT testing frameworks
Bad organisation
Increased duplication Overlap Unit Tests Integration Tests UI System Acceptance Tests Overlap
STOPPED
Unit Tests Acceptance Tests
Outside-in Development
Cucumber http://www.flickr.com/photos/vizzzual-dot-com/2738586453/
Feature: Creating a schedule 	In Order to book meetings 	The manager 	Needs to be able to view a teams calendar Scenario: View calendar of another view Given “Bob” has a public calendar When the manager views “Bob”’s calendar Then an empty calendar should be shown
Given /^”([^quot;]*)” has a public calendar$/ do |user|    pending End When /^ the manager views “([^quot;]*)”’s calendar$/ do |user|    pending End Then /^ an empty calendar should be shown $/ do    pending end
Thanks to TekPub for Kona sample
Thanks to TekPub for Kona sample
Feature: Display Products   In order to browse the catalog   The customer   Needs to see products Scenario: Single featured product on homepage     Given the featured product "Adventure Works 20x30 Binoculars"     When I visit the homepage     Then I should see "Adventure Works 20x30 Binoculars" listed under "Featured"
WebRat http://www.flickr.com/photos/whatwhat/22624256/
visit click_link fill_in click_button check and uncheck choose select attach_file
Given /^the featured product "([^quot;]*)"$/ do |product_name| Product.createproduct_name, ‘featured’ end
When /^I visit the homepage$/ do   visit url + '/' end
Then /^I should see "([^quot;]*)" listed under "([^quot;]*)"$/ do |product, area|   within div_id(area) do |products| products.should contain(product)   end End def div_id(area)   "#" + area.downcase.underscore end
Dynamically replaced env_selenium.rb def url   "http://www.website.local" end Webrat.configure do |config| config.mode = :selenium config.application_framework = :external config.selenium_browser_key = get_browser_key   puts "Executing tests using the browser #{config.selenium_browser_key}" end def get_browser_key()   command = "*firefox"   command = ENV['BROWSER'] if ENV['BROWSER']   return command end
cucumber --profile selenium browser=*firefox cucumber --profile selenium browser=*safari cucumber --profile selenium browser=*iexplore cucumber --profile selenium browser=*googlechrome
cucumber --profile webrat HEADLESS BROWSING BY REPLACING ENV.RB
Scenario Outline: Blowout Specials     Given <product> in "Blowout Specials"     When I visit the homepage     Then I should see <product> listed under "Blowout Specials"     Examples:       | product                                                         |       |  "Cascade Fur-lined Hiking Boots"           |       |  "Trailhead Locking Carabiner"                 |       |  "Climbing Rope with Single Caribiner"   |
Before do open_connection empty_database end at_exit do empty_database end Multiple Hooks
Multiple extension frameworks Test command line applications Test Silverlightlex Test WPF based desktop applications Execute in parallel across multiple machines
HUGE RE-USE == VALUE
http://www.flickr.com/photos/leon_homan/2856628778/
Focus on finding true value Look at other communities for advice, support and inspiration
@Ben_Hall Ben@BenHall.me.uk Blog.BenHall.me.uk http://lolcatgenerator.com/lolcat/120/
Lonestar
using Cuke4Nuke.Framework; usingNUnit.Framework; usingWatiN.Core; namespaceGoogle.StepDefinitions {     publicclassSearchSteps     {         Browser _browser;          [Before]         publicvoidSetUp()         {             _browser = new WatiN.Core.IE();         }         [After]         publicvoidTearDown()         {             if (_browser != null)             {                 _browser.Dispose();             }         }         [When(@"^(?:I'm on|I go to) the search page$")]         publicvoidGoToSearchPage()         {             _browser.GoTo("http://www.google.com/");         }         [When("^I search for quot;(.*)quot;$")]         publicvoidSearchFor(string query)         {             _browser.TextField(Find.ByName("q")).TypeText(query);             _browser.Button(Find.ByName("btnG")).Click();         }         [Then("^I should be on the search page$")]         publicvoidIsOnSearchPage()         {             Assert.That(_browser.Title == "Google");         }         [Then("^I should see quot;(.*)quot; in the results$")]         publicvoidResultsContain(stringexpectedResult)         {             Assert.That(_browser.ContainsText(expectedResult));         }     } }
Given /^(?:I'm on|I go to) the search page$/ do   visit 'http://www.google.com' end   When /^I search for "([^quot;]*)"$/ do|query|   fill_in 'q', :with => query   click_button 'Google Search' end   Then /^I should be on the search page$/ do  dom.search('title').should == "Google" end   Then /^I should see quot;(.*)quot; in the results$/ do|text|   response.should contain(text) end
Software Recommended: IronRuby Ruby Cucumber Rspec WebRat mechanize Selenium RC selenium-client Caricature activerecord-sqlserver-adapter Optional: XSP Mono JetBrain’sRubyMine JRuby Capybara Celerity Active record  active-record-model-generator Faker Guid
Useful Links http://www.github.com/BenHall http://blog.benhall.me.uk http://stevehodgkiss.com/2009/11/14/using-activerecord-migrator-standalone-with-sqlite-and-sqlserver-on-windows.html http://www.testingaspnet.com http:// http://msdn.microsoft.com/en-us/magazine/dd434651.aspx http://msdn.microsoft.com/en-us/magazine/dd453038.aspx http://www.cukes.info
SQL Server and Ruby gem install activerecord-sqlserver-adapter Download dbi-0.2.2.zip  Extract dbdDO.rb to rubyite_ruby.8BDDO.rb

More Related Content

What's hot

Kiss PageObjects [01-2017]
Kiss PageObjects [01-2017]Kiss PageObjects [01-2017]
Kiss PageObjects [01-2017]Iakiv Kramarenko
 
RESTful services and OAUTH protocol in IoT
RESTful services and OAUTH protocol in IoTRESTful services and OAUTH protocol in IoT
RESTful services and OAUTH protocol in IoTYakov Fain
 
AngularJS best-practices
AngularJS best-practicesAngularJS best-practices
AngularJS best-practicesHenry Tao
 
5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniter5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniternicdev
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperfNew Relic
 
Controller Testing: You're Doing It Wrong
Controller Testing: You're Doing It WrongController Testing: You're Doing It Wrong
Controller Testing: You're Doing It Wrongjohnnygroundwork
 
AtlasCamp 2015: Web technologies you should be using now
AtlasCamp 2015: Web technologies you should be using nowAtlasCamp 2015: Web technologies you should be using now
AtlasCamp 2015: Web technologies you should be using nowAtlassian
 
React Native Workshop - React Alicante
React Native Workshop - React AlicanteReact Native Workshop - React Alicante
React Native Workshop - React AlicanteIgnacio Martín
 
Angular JS - Introduction
Angular JS - IntroductionAngular JS - Introduction
Angular JS - IntroductionSagar Acharya
 
Automation Abstractions: Page Objects and Beyond
Automation Abstractions: Page Objects and BeyondAutomation Abstractions: Page Objects and Beyond
Automation Abstractions: Page Objects and BeyondTechWell
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and EasybIakiv Kramarenko
 
Understanding angular js
Understanding angular jsUnderstanding angular js
Understanding angular jsAayush Shrestha
 
Ajax Applications with RichFaces and JSF 2
Ajax Applications with RichFaces and JSF 2Ajax Applications with RichFaces and JSF 2
Ajax Applications with RichFaces and JSF 2Max Katz
 

What's hot (20)

Angularjs
AngularjsAngularjs
Angularjs
 
Solid angular
Solid angularSolid angular
Solid angular
 
Magento Indexes
Magento IndexesMagento Indexes
Magento Indexes
 
Kiss PageObjects [01-2017]
Kiss PageObjects [01-2017]Kiss PageObjects [01-2017]
Kiss PageObjects [01-2017]
 
RESTful services and OAUTH protocol in IoT
RESTful services and OAUTH protocol in IoTRESTful services and OAUTH protocol in IoT
RESTful services and OAUTH protocol in IoT
 
Gae
GaeGae
Gae
 
AngularJS best-practices
AngularJS best-practicesAngularJS best-practices
AngularJS best-practices
 
5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniter5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniter
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperf
 
Controller Testing: You're Doing It Wrong
Controller Testing: You're Doing It WrongController Testing: You're Doing It Wrong
Controller Testing: You're Doing It Wrong
 
AtlasCamp 2015: Web technologies you should be using now
AtlasCamp 2015: Web technologies you should be using nowAtlasCamp 2015: Web technologies you should be using now
AtlasCamp 2015: Web technologies you should be using now
 
React Native Workshop - React Alicante
React Native Workshop - React AlicanteReact Native Workshop - React Alicante
React Native Workshop - React Alicante
 
Angular JS - Introduction
Angular JS - IntroductionAngular JS - Introduction
Angular JS - Introduction
 
I Love codeigniter, You?
I Love codeigniter, You?I Love codeigniter, You?
I Love codeigniter, You?
 
Extend sdk
Extend sdkExtend sdk
Extend sdk
 
Automation Abstractions: Page Objects and Beyond
Automation Abstractions: Page Objects and BeyondAutomation Abstractions: Page Objects and Beyond
Automation Abstractions: Page Objects and Beyond
 
Introduction to Unit Tests and TDD
Introduction to Unit Tests and TDDIntroduction to Unit Tests and TDD
Introduction to Unit Tests and TDD
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and Easyb
 
Understanding angular js
Understanding angular jsUnderstanding angular js
Understanding angular js
 
Ajax Applications with RichFaces and JSF 2
Ajax Applications with RichFaces and JSF 2Ajax Applications with RichFaces and JSF 2
Ajax Applications with RichFaces and JSF 2
 

Viewers also liked

Unit 4 Project
Unit 4 ProjectUnit 4 Project
Unit 4 Projectlilmxdkid
 
Sinh hoat CLB tin hoc Komaba lan 2 - Phat bieu cua Ngoc
Sinh hoat CLB tin hoc Komaba lan 2 - Phat bieu cua NgocSinh hoat CLB tin hoc Komaba lan 2 - Phat bieu cua Ngoc
Sinh hoat CLB tin hoc Komaba lan 2 - Phat bieu cua NgocNgoc Dao
 
Asp net
Asp netAsp net
Asp netquanvn
 
Bai giang-lap-trinh-web-bang-asp
Bai giang-lap-trinh-web-bang-aspBai giang-lap-trinh-web-bang-asp
Bai giang-lap-trinh-web-bang-aspVu Nguyen Van
 
Intro To Asp Net And Web Forms
Intro To Asp Net And Web FormsIntro To Asp Net And Web Forms
Intro To Asp Net And Web FormsSAMIR BHOGAYTA
 
Introduction to ASP.NET
Introduction to ASP.NETIntroduction to ASP.NET
Introduction to ASP.NETPeter Gfader
 
Developing an ASP.NET Web Application
Developing an ASP.NET Web ApplicationDeveloping an ASP.NET Web Application
Developing an ASP.NET Web ApplicationRishi Kothari
 

Viewers also liked (12)

Unit 4 Project
Unit 4 ProjectUnit 4 Project
Unit 4 Project
 
Tìm hiểu về website
Tìm hiểu về websiteTìm hiểu về website
Tìm hiểu về website
 
Sinh hoat CLB tin hoc Komaba lan 2 - Phat bieu cua Ngoc
Sinh hoat CLB tin hoc Komaba lan 2 - Phat bieu cua NgocSinh hoat CLB tin hoc Komaba lan 2 - Phat bieu cua Ngoc
Sinh hoat CLB tin hoc Komaba lan 2 - Phat bieu cua Ngoc
 
Asp net
Asp netAsp net
Asp net
 
Bai giang-lap-trinh-web-bang-asp
Bai giang-lap-trinh-web-bang-aspBai giang-lap-trinh-web-bang-asp
Bai giang-lap-trinh-web-bang-asp
 
Asp
AspAsp
Asp
 
Controls
ControlsControls
Controls
 
Intro To Asp Net And Web Forms
Intro To Asp Net And Web FormsIntro To Asp Net And Web Forms
Intro To Asp Net And Web Forms
 
Note d'intention
Note d'intentionNote d'intention
Note d'intention
 
Introduction to ASP.NET
Introduction to ASP.NETIntroduction to ASP.NET
Introduction to ASP.NET
 
Cookies and sessions
Cookies and sessionsCookies and sessions
Cookies and sessions
 
Developing an ASP.NET Web Application
Developing an ASP.NET Web ApplicationDeveloping an ASP.NET Web Application
Developing an ASP.NET Web Application
 

Similar to Testing C# and ASP.net using Ruby techniques

Ride on the Fast Track of Web with Ruby on Rails- Part 2
Ride on the Fast Track of Web with Ruby on Rails- Part 2Ride on the Fast Track of Web with Ruby on Rails- Part 2
Ride on the Fast Track of Web with Ruby on Rails- Part 2A.K.M. Ahsrafuzzaman
 
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using RubyTesting ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using RubyBen Hall
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialYi-Ting Cheng
 
Introduction to ASP.NET MVC
Introduction to ASP.NET MVCIntroduction to ASP.NET MVC
Introduction to ASP.NET MVCMaarten Balliauw
 
Angular JS2 Training Session #2
Angular JS2 Training Session #2Angular JS2 Training Session #2
Angular JS2 Training Session #2Paras Mendiratta
 
ActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group PresentationActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group Presentationipolevoy
 
Course CodeSchool - Shaping up with Angular.js
Course CodeSchool - Shaping up with Angular.jsCourse CodeSchool - Shaping up with Angular.js
Course CodeSchool - Shaping up with Angular.jsVinícius de Moraes
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to DjangoJames Casey
 
01 startoff angularjs
01 startoff angularjs01 startoff angularjs
01 startoff angularjsErhwen Kuo
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenerytoddbr
 
SharePoint Saturday Atlanta 2015
SharePoint Saturday Atlanta 2015SharePoint Saturday Atlanta 2015
SharePoint Saturday Atlanta 2015Pushkar Chivate
 
Spring MVC
Spring MVCSpring MVC
Spring MVCyuvalb
 
Controllers & actions
Controllers & actionsControllers & actions
Controllers & actionsEyal Vardi
 

Similar to Testing C# and ASP.net using Ruby techniques (20)

Ride on the Fast Track of Web with Ruby on Rails- Part 2
Ride on the Fast Track of Web with Ruby on Rails- Part 2Ride on the Fast Track of Web with Ruby on Rails- Part 2
Ride on the Fast Track of Web with Ruby on Rails- Part 2
 
Catalog display
Catalog displayCatalog display
Catalog display
 
The Rails Way
The Rails WayThe Rails Way
The Rails Way
 
Testing ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using RubyTesting ASP.net Web Applications using Ruby
Testing ASP.net Web Applications using Ruby
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
 
mean stack
mean stackmean stack
mean stack
 
AngularJs-training
AngularJs-trainingAngularJs-training
AngularJs-training
 
Introduction to ASP.NET MVC
Introduction to ASP.NET MVCIntroduction to ASP.NET MVC
Introduction to ASP.NET MVC
 
Angular JS2 Training Session #2
Angular JS2 Training Session #2Angular JS2 Training Session #2
Angular JS2 Training Session #2
 
Continuous Quality
Continuous QualityContinuous Quality
Continuous Quality
 
ActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group PresentationActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group Presentation
 
Course CodeSchool - Shaping up with Angular.js
Course CodeSchool - Shaping up with Angular.jsCourse CodeSchool - Shaping up with Angular.js
Course CodeSchool - Shaping up with Angular.js
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
01 startoff angularjs
01 startoff angularjs01 startoff angularjs
01 startoff angularjs
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 
Wt unit 5
Wt unit 5Wt unit 5
Wt unit 5
 
SharePoint Saturday Atlanta 2015
SharePoint Saturday Atlanta 2015SharePoint Saturday Atlanta 2015
SharePoint Saturday Atlanta 2015
 
Codegnitorppt
CodegnitorpptCodegnitorppt
Codegnitorppt
 
Spring MVC
Spring MVCSpring MVC
Spring MVC
 
Controllers & actions
Controllers & actionsControllers & actions
Controllers & actions
 

More from Ben Hall

The Art Of Documentation - NDC Porto 2022
The Art Of Documentation - NDC Porto 2022The Art Of Documentation - NDC Porto 2022
The Art Of Documentation - NDC Porto 2022Ben Hall
 
The Art Of Documentation for Open Source Projects
The Art Of Documentation for Open Source ProjectsThe Art Of Documentation for Open Source Projects
The Art Of Documentation for Open Source ProjectsBen Hall
 
Three Years of Lessons Running Potentially Malicious Code Inside Containers
Three Years of Lessons Running Potentially Malicious Code Inside ContainersThree Years of Lessons Running Potentially Malicious Code Inside Containers
Three Years of Lessons Running Potentially Malicious Code Inside ContainersBen Hall
 
Containers without docker
Containers without dockerContainers without docker
Containers without dockerBen Hall
 
Deploying windows containers with kubernetes
Deploying windows containers with kubernetesDeploying windows containers with kubernetes
Deploying windows containers with kubernetesBen Hall
 
The Art of Documentation and Readme.md for Open Source Projects
The Art of Documentation and Readme.md for Open Source ProjectsThe Art of Documentation and Readme.md for Open Source Projects
The Art of Documentation and Readme.md for Open Source ProjectsBen Hall
 
How Secure Are Docker Containers?
How Secure Are Docker Containers?How Secure Are Docker Containers?
How Secure Are Docker Containers?Ben Hall
 
The Challenges of Becoming Cloud Native
The Challenges of Becoming Cloud NativeThe Challenges of Becoming Cloud Native
The Challenges of Becoming Cloud NativeBen Hall
 
Scaling Docker Containers using Kubernetes and Azure Container Service
Scaling Docker Containers using Kubernetes and Azure Container ServiceScaling Docker Containers using Kubernetes and Azure Container Service
Scaling Docker Containers using Kubernetes and Azure Container ServiceBen Hall
 
The art of documentation and readme.md
The art of documentation and readme.mdThe art of documentation and readme.md
The art of documentation and readme.mdBen Hall
 
Experimenting and Learning Kubernetes and Tensorflow
Experimenting and Learning Kubernetes and TensorflowExperimenting and Learning Kubernetes and Tensorflow
Experimenting and Learning Kubernetes and TensorflowBen Hall
 
Running .NET on Docker
Running .NET on DockerRunning .NET on Docker
Running .NET on DockerBen Hall
 
Real World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationReal World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationBen Hall
 
Tips on solving E_TOO_MANY_THINGS_TO_LEARN with Kubernetes
Tips on solving E_TOO_MANY_THINGS_TO_LEARN with KubernetesTips on solving E_TOO_MANY_THINGS_TO_LEARN with Kubernetes
Tips on solving E_TOO_MANY_THINGS_TO_LEARN with KubernetesBen Hall
 
Deploying applications to Windows Server 2016 and Windows Containers
Deploying applications to Windows Server 2016 and Windows ContainersDeploying applications to Windows Server 2016 and Windows Containers
Deploying applications to Windows Server 2016 and Windows ContainersBen Hall
 
The How and Why of Windows containers
The How and Why of Windows containersThe How and Why of Windows containers
The How and Why of Windows containersBen Hall
 
Lessons from running potentially malicious code inside containers
Lessons from running potentially malicious code inside containersLessons from running potentially malicious code inside containers
Lessons from running potentially malicious code inside containersBen Hall
 
Deploying Windows Containers on Windows Server 2016
Deploying Windows Containers on Windows Server 2016Deploying Windows Containers on Windows Server 2016
Deploying Windows Containers on Windows Server 2016Ben Hall
 
Learning Patterns for the Overworked Developer
Learning Patterns for the Overworked DeveloperLearning Patterns for the Overworked Developer
Learning Patterns for the Overworked DeveloperBen Hall
 
Real World Lessons on the Pain Points of Node.js Applications
Real World Lessons on the Pain Points of Node.js ApplicationsReal World Lessons on the Pain Points of Node.js Applications
Real World Lessons on the Pain Points of Node.js ApplicationsBen Hall
 

More from Ben Hall (20)

The Art Of Documentation - NDC Porto 2022
The Art Of Documentation - NDC Porto 2022The Art Of Documentation - NDC Porto 2022
The Art Of Documentation - NDC Porto 2022
 
The Art Of Documentation for Open Source Projects
The Art Of Documentation for Open Source ProjectsThe Art Of Documentation for Open Source Projects
The Art Of Documentation for Open Source Projects
 
Three Years of Lessons Running Potentially Malicious Code Inside Containers
Three Years of Lessons Running Potentially Malicious Code Inside ContainersThree Years of Lessons Running Potentially Malicious Code Inside Containers
Three Years of Lessons Running Potentially Malicious Code Inside Containers
 
Containers without docker
Containers without dockerContainers without docker
Containers without docker
 
Deploying windows containers with kubernetes
Deploying windows containers with kubernetesDeploying windows containers with kubernetes
Deploying windows containers with kubernetes
 
The Art of Documentation and Readme.md for Open Source Projects
The Art of Documentation and Readme.md for Open Source ProjectsThe Art of Documentation and Readme.md for Open Source Projects
The Art of Documentation and Readme.md for Open Source Projects
 
How Secure Are Docker Containers?
How Secure Are Docker Containers?How Secure Are Docker Containers?
How Secure Are Docker Containers?
 
The Challenges of Becoming Cloud Native
The Challenges of Becoming Cloud NativeThe Challenges of Becoming Cloud Native
The Challenges of Becoming Cloud Native
 
Scaling Docker Containers using Kubernetes and Azure Container Service
Scaling Docker Containers using Kubernetes and Azure Container ServiceScaling Docker Containers using Kubernetes and Azure Container Service
Scaling Docker Containers using Kubernetes and Azure Container Service
 
The art of documentation and readme.md
The art of documentation and readme.mdThe art of documentation and readme.md
The art of documentation and readme.md
 
Experimenting and Learning Kubernetes and Tensorflow
Experimenting and Learning Kubernetes and TensorflowExperimenting and Learning Kubernetes and Tensorflow
Experimenting and Learning Kubernetes and Tensorflow
 
Running .NET on Docker
Running .NET on DockerRunning .NET on Docker
Running .NET on Docker
 
Real World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationReal World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS Application
 
Tips on solving E_TOO_MANY_THINGS_TO_LEARN with Kubernetes
Tips on solving E_TOO_MANY_THINGS_TO_LEARN with KubernetesTips on solving E_TOO_MANY_THINGS_TO_LEARN with Kubernetes
Tips on solving E_TOO_MANY_THINGS_TO_LEARN with Kubernetes
 
Deploying applications to Windows Server 2016 and Windows Containers
Deploying applications to Windows Server 2016 and Windows ContainersDeploying applications to Windows Server 2016 and Windows Containers
Deploying applications to Windows Server 2016 and Windows Containers
 
The How and Why of Windows containers
The How and Why of Windows containersThe How and Why of Windows containers
The How and Why of Windows containers
 
Lessons from running potentially malicious code inside containers
Lessons from running potentially malicious code inside containersLessons from running potentially malicious code inside containers
Lessons from running potentially malicious code inside containers
 
Deploying Windows Containers on Windows Server 2016
Deploying Windows Containers on Windows Server 2016Deploying Windows Containers on Windows Server 2016
Deploying Windows Containers on Windows Server 2016
 
Learning Patterns for the Overworked Developer
Learning Patterns for the Overworked DeveloperLearning Patterns for the Overworked Developer
Learning Patterns for the Overworked Developer
 
Real World Lessons on the Pain Points of Node.js Applications
Real World Lessons on the Pain Points of Node.js ApplicationsReal World Lessons on the Pain Points of Node.js Applications
Real World Lessons on the Pain Points of Node.js Applications
 

Recently uploaded

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 

Recently uploaded (20)

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 

Testing C# and ASP.net using Ruby techniques

  • 1. Testing C# and ASP.net using Ruby Meerkatalyst @Ben_HallBen@BenHall.me.ukBlog.BenHall.me.uk
  • 2. London based C# MVPWeb Developer @ 7digital.com Working on a number of Open Source Projects Co-Author of Testing ASP.net Web Applications http://www.testingaspnet.com
  • 3. How we can apply Ruby testing techniques to C# - In mindset - In practice 1| Object Level testing2| Systems testing
  • 6. Realised Ruby doesn’t have as many problems as .net
  • 9. I love writing tests upfront
  • 10. Not sure about implementation According to various TDD books blogs
  • 11. Help with an initial design but what about long term?
  • 13.
  • 19.
  • 20. Ruby (via IronRuby) p = ProductController.new(nil) C# public class ProductController : Controller { IStoreService _service; public ProductController(IStoreService service) { _service = service; } } Thanks to TekPub for Kona sample
  • 21. Define the context C# public ActionResult Index(int? id) { ProductListViewModel model = null; if (id.HasValue) model = _service.GetHomeModel(id.Value); else return RedirectToAction("Index", "Home"); return View(model); } Ruby (via IronRuby) describe ProductController, “Product homepage requested" do context "when Category ID is empty" do end end Thanks to TekPub for Kona sample
  • 22. Create the context $: << ‘../../Kona/bin/’ require ‘Kona.dll’ Include Kona::Controllers describe ProductController, “Product homepage requested" do context "when Category ID is empty" do end end Thanks to TekPub for Kona sample
  • 23. Create the context require '../spec_helper‘ describe ProductController, “Product homepage requested" do context "when Category ID is empty" do end end Thanks to TekPub for Kona sample
  • 24. Create the context require '../spec_helper‘ describe ProductController, “Product homepage requested" do context "when Category ID is empty" do before(:each) do controller = ProductController.new nil category_id = nil @result = controller.Indexcategory_id end end end Thanks to TekPub for Kona sample
  • 25. Define the spec require '../spec_helper‘ describe ProductController, “Product homepage requested" do context “with empty Category ID" do before(:each) do ... End it "should redirect to main landing page" do @result.route_values[‘controller'].should == ‘Index’ @result.route_values[‘home'].should == ‘Home’ end end Thanks to TekPub for Kona sample
  • 26. Stubbing via caricature context “with validCategory ID" do Before(:each) view_model = product_list('Test Category') service = isolate Services::IStoreService service.when_receiving(:get_home_model).with(valid_category_id).return(view_model) controller = ProductController.new service @result = controller.Indexvalid_category_id end it “returns a view model” do @result.view_model.should_not == nil end it “should return name of selected category” do @result.view_model.selected_category.name.should == 'Test Category‘ end end Thanks to TekPub for Kona sample
  • 27. Tests and Databases describe Services::StoreService do before(:all) do session = NHibernate::create_session NHibernate::insert_category session Services::StoreService.new session @model = service.get_home_model 0 end it "should return constructed object" do @model.should_notbe_nil end it "should return all categories from database" do @model.Categories.to_a.Count.should == 1 end end Thanks to TekPub for Kona sample
  • 29. [Subject(typeof(HomeController))]public class when_the_navigation_controller_is_asked_for_the_header : specification_for_navigation_controller{ static ActionResult result; Establish context = () => identity_tasks.Stub(i => i.IsSignedIn()).Return(true); Because of = () => result = subject.Menu(); It should_ask_the_identity_tasks_if_the_user_is_signed_in = () => identity_tasks.AssertWasCalled(x => x.IsSignedIn()); It should_return_the_default_view = () => result.ShouldBeAView().And().ViewName.ShouldBeEmpty(); It should_not_use_a_master_page = () => result.ShouldBeAView().And().MasterName.ShouldBeEmpty(); It should_set_the_view_model_property_to_a_new_menu_view_model = () =>result.Model<MenuViewModel>().ShouldNotBeNull(); It should_set_the_properties_of_the_view_model_correctly = () => result.Model<MenuViewModel>().IsLoggedIn.ShouldBeTrue(); }
  • 30. describe HomeController, “When the navigation controller is asked for the header” do before(:all) do @identity_tasks.Stub(i => i.IsSignedIn()).Return(true); @result = subject.Menu(); end it “should ask the identity tasks if the user is signed in” do @identity_tasks.did_receive(:is_signed_in) .should be_successful end it “should return the default view” do @result.shouldbe_view @result.view_name.shouldbe_empty end it “should not use a master page” do @result.shouldbe_view @result.master_name.shouldbe_empty end it “should set the view model property to a new menu view model” do @result.shouldbe_view @result.model.should_notbe_nil end it “should set the properties of the view model correctly” do @result.model.is_logged_in.shouldbe_true endend
  • 31. Consider your test suite containing > 500 tests Each test matters. But each problem hurts more
  • 32. Share specs share_examples_for "unauthorized user" do it 'sets an-error message' do result.view_model.error_message.should == "Sorry, you need to login to access." end it 'redirects to the login page' do result.view_name.should end end describe CheckoutController do it_should_behave_like “unauthorized user“describe AccountController doit_should_behave_like “unauthorized user“
  • 33. Include additional functionality require ‘nhibernate_helpers’require ‘product_creation_extensions’require ‘customer_creation_extensions’describe ProductController do
  • 34. model.Categories.to_a.Count.should == 1 model.Categories.should have(1) module Matchers class CountCheck def initialize(expected) @expected = expected end def matches?(actual) actual.to_a.Count() == @expected end end def have(expected) CountCheck.new(expected) end end Duck Typing FTW!
  • 35. Dynamically create specs def find_products(category)Product.Find(:all, :conditions=> “category #{category}”)enddescribe ‘products should be able to be added to basket' do before(:all) do @basket = Basket.new endfind_products(‘Boots’).each do |p| it “can add #{p.product_name} to basket" do @basket.add_item p.id @basket.should contain(p) end endend
  • 37. I’m against integration tests Or at least 90% of them
  • 41. 5174 passed, 491 failed, 94 skipped
  • 42. “Tests aren’t failing because of defects”
  • 43. ‘Nearly’ end-to-end While knowing about everything in the middle...
  • 44. Becomes a pain to refactor
  • 45. FEAR
  • 46. FEAR
  • 49. Increased duplication Overlap Unit Tests Integration Tests UI System Acceptance Tests Overlap
  • 54. Feature: Creating a schedule In Order to book meetings The manager Needs to be able to view a teams calendar Scenario: View calendar of another view Given “Bob” has a public calendar When the manager views “Bob”’s calendar Then an empty calendar should be shown
  • 55. Given /^”([^quot;]*)” has a public calendar$/ do |user| pending End When /^ the manager views “([^quot;]*)”’s calendar$/ do |user| pending End Then /^ an empty calendar should be shown $/ do pending end
  • 56. Thanks to TekPub for Kona sample
  • 57. Thanks to TekPub for Kona sample
  • 58. Feature: Display Products In order to browse the catalog The customer Needs to see products Scenario: Single featured product on homepage Given the featured product "Adventure Works 20x30 Binoculars" When I visit the homepage Then I should see "Adventure Works 20x30 Binoculars" listed under "Featured"
  • 60. visit click_link fill_in click_button check and uncheck choose select attach_file
  • 61. Given /^the featured product "([^quot;]*)"$/ do |product_name| Product.createproduct_name, ‘featured’ end
  • 62. When /^I visit the homepage$/ do visit url + '/' end
  • 63. Then /^I should see "([^quot;]*)" listed under "([^quot;]*)"$/ do |product, area| within div_id(area) do |products| products.should contain(product) end End def div_id(area) "#" + area.downcase.underscore end
  • 64. Dynamically replaced env_selenium.rb def url "http://www.website.local" end Webrat.configure do |config| config.mode = :selenium config.application_framework = :external config.selenium_browser_key = get_browser_key puts "Executing tests using the browser #{config.selenium_browser_key}" end def get_browser_key() command = "*firefox" command = ENV['BROWSER'] if ENV['BROWSER'] return command end
  • 65. cucumber --profile selenium browser=*firefox cucumber --profile selenium browser=*safari cucumber --profile selenium browser=*iexplore cucumber --profile selenium browser=*googlechrome
  • 66. cucumber --profile webrat HEADLESS BROWSING BY REPLACING ENV.RB
  • 67. Scenario Outline: Blowout Specials Given <product> in "Blowout Specials" When I visit the homepage Then I should see <product> listed under "Blowout Specials" Examples: | product | | "Cascade Fur-lined Hiking Boots" | | "Trailhead Locking Carabiner" | | "Climbing Rope with Single Caribiner" |
  • 68. Before do open_connection empty_database end at_exit do empty_database end Multiple Hooks
  • 69. Multiple extension frameworks Test command line applications Test Silverlightlex Test WPF based desktop applications Execute in parallel across multiple machines
  • 70. HUGE RE-USE == VALUE
  • 72. Focus on finding true value Look at other communities for advice, support and inspiration
  • 73. @Ben_Hall Ben@BenHall.me.uk Blog.BenHall.me.uk http://lolcatgenerator.com/lolcat/120/
  • 75. using Cuke4Nuke.Framework; usingNUnit.Framework; usingWatiN.Core; namespaceGoogle.StepDefinitions {     publicclassSearchSteps     {         Browser _browser; [Before]         publicvoidSetUp()         {             _browser = new WatiN.Core.IE();         } [After]         publicvoidTearDown()         {             if (_browser != null)             {                 _browser.Dispose();             }         } [When(@"^(?:I'm on|I go to) the search page$")]         publicvoidGoToSearchPage()         {             _browser.GoTo("http://www.google.com/");         } [When("^I search for quot;(.*)quot;$")]         publicvoidSearchFor(string query)         {             _browser.TextField(Find.ByName("q")).TypeText(query);             _browser.Button(Find.ByName("btnG")).Click();         } [Then("^I should be on the search page$")]         publicvoidIsOnSearchPage()         {             Assert.That(_browser.Title == "Google");         } [Then("^I should see quot;(.*)quot; in the results$")]         publicvoidResultsContain(stringexpectedResult)         {             Assert.That(_browser.ContainsText(expectedResult));         }     } }
  • 76. Given /^(?:I'm on|I go to) the search page$/ do   visit 'http://www.google.com' end   When /^I search for "([^quot;]*)"$/ do|query|   fill_in 'q', :with => query   click_button 'Google Search' end   Then /^I should be on the search page$/ do  dom.search('title').should == "Google" end   Then /^I should see quot;(.*)quot; in the results$/ do|text|   response.should contain(text) end
  • 77. Software Recommended: IronRuby Ruby Cucumber Rspec WebRat mechanize Selenium RC selenium-client Caricature activerecord-sqlserver-adapter Optional: XSP Mono JetBrain’sRubyMine JRuby Capybara Celerity Active record active-record-model-generator Faker Guid
  • 78. Useful Links http://www.github.com/BenHall http://blog.benhall.me.uk http://stevehodgkiss.com/2009/11/14/using-activerecord-migrator-standalone-with-sqlite-and-sqlserver-on-windows.html http://www.testingaspnet.com http:// http://msdn.microsoft.com/en-us/magazine/dd434651.aspx http://msdn.microsoft.com/en-us/magazine/dd453038.aspx http://www.cukes.info
  • 79. SQL Server and Ruby gem install activerecord-sqlserver-adapter Download dbi-0.2.2.zip Extract dbdDO.rb to rubyite_ruby.8BDDO.rb

Editor's Notes

  1. Cost of defects to 0Every test needs to justify itselfBut not just justify, add value both during the initial development and going forward. After working on a number of large scale .net based automation projects I started to question how much value I was adding to the project. This lead me to look at other communities as inspiration
  2. More abstracted away... As such nicer for testingMore fluid, more human readable.Perfect for tests. This is why I looked at how I can start using Ruby both in practice and mindset
  3. Cleaner, more focused designDefining how it’s meant to workProvide documentation for myself and team members over coming monthsyears of projectRefactoring
  4. Naming Implementation might go though multiple interactions until I reach my desired behaviour.
  5. Or at least, that’s what I would like..Net Problems- Unit doesn’t represent the concept of real world software - Legacy where nothing is a unit - Mentoring
  6. System brings together different parts to solve a particular problem
  7. Behaviour can be isolated units like TDDBut also accept that it might involve a number of other classes Defining the behaviour of our system, means we aren’t too focused on
  8. Feature Coverage
  9. Often forgot in the .Net world...Started to come more maintain stream thanks to Aaron Jenson and Scott BellwareBounded contexts
  10. http://whocanhelpme.codeplex.com/Good example of how to use Mspec with MVC. Sadly, I think Rspec has a nicer syntax.Naming + tests are very good.
  11. get_div_id == “Design UI for Testability”
  12. get_div_id == “Design UI for Testability”
  13. get_div_id == “Design UI for Testability”
  14. get_div_id == “Design UI for Testability”
  15. get_div_id == “Design UI for Testability”