SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    SitePoint Guru Skyblaze's Avatar
    Join Date
    Jul 2005
    Location
    Italy
    Posts
    734
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Tests questions...

    I don't understand which is the purpose of rails tests when you write a test that tests a simple functionality that already works if you use it in a browser. This is the same that happens for example in the book where the author write "silly" test to test a thing that is perfectly checkable in a live browser situation. I mean at least i can firstable test the functionality live in a browser than if something goes wrong i can wrtie a test for it...is that wrong?

  2. #2
    ☆★☆★ silver trophy vgarcia's Avatar
    Join Date
    Jan 2002
    Location
    in transition
    Posts
    21,235
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    No it's not wrong, it's just a difference of approach. Functional/integration testing is just hard proof that your app/site works the way it's supposed to, without having to load up the browser. Yes you still have to do browser-level testing, but if you already know for example that if you click a button a div named "results" will appear on the page, then you only have to concern yourself with how the "results" div looks when it comes time to browser test.

    Getting the tests working first will save you time on the browser-level testing, since at that point you've ruled out any possible functionality problem and anything that goes wrong in your browser testing will probably be fixable with CSS or Javascript.

  3. #3
    SitePoint Guru Skyblaze's Avatar
    Join Date
    Jul 2005
    Location
    Italy
    Posts
    734
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by vgarcia View Post
    No it's not wrong, it's just a difference of approach. Functional/integration testing is just hard proof that your app/site works the way it's supposed to, without having to load up the browser. Yes you still have to do browser-level testing, but if you already know for example that if you click a button a div named "results" will appear on the page, then you only have to concern yourself with how the "results" div looks when it comes time to browser test.

    Getting the tests working first will save you time on the browser-level testing, since at that point you've ruled out any possible functionality problem and anything that goes wrong in your browser testing will probably be fixable with CSS or Javascript.
    ok but i think it is "stupid" to write a test to see if a div is rendered from the command line when i can fire up the browser and see it there and in a better way

  4. #4
    ☆★☆★ silver trophy vgarcia's Avatar
    Join Date
    Jan 2002
    Location
    in transition
    Posts
    21,235
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by Skyblaze View Post
    ok but i think it is "stupid" to write a test to see if a div is rendered from the command line when i can fire up the browser and see it there and in a better way
    Okay, YOU fire up the browser and make sure the div's there. But let's say someone else has to maintain your code. Will they know why the div is there and what it's supposed to do? With a test written, they'll be able to figure it out easier than with no test.

  5. #5
    SitePoint Zealot tconley79's Avatar
    Join Date
    Feb 2004
    Location
    Miami
    Posts
    176
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Also, consider this:

    Without a test suite, you can easily use your browser to check if things are in order on Day 1 of your project development. Everything is pretty simple then.

    Fast forward to day 30 when you've built your app up A LOT. There's more chance at this stage that if some simple component you created on day 1 fails, you might not catch it because of everything else that's going on.

    Having a test suite that grows with your project makes sure you don't let this slip by later. It helps make sure everything works all the time--from the simplest equality check to a complex redirect.

  6. #6
    Resident Java Hater
    Join Date
    Jul 2004
    Location
    Gerodieville Central, UK
    Posts
    446
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Seeing as most people learn by example, here's a good scenario that demonstrates the requirement for testing.

    Say you have a site like eBay, where people can "save searches". One of the options when you save a search is to let the system give you notifications when new items meet the search criteria, or items are removed that fit the criteria.

    Testing this manually is a PITA at the best of times. When you manually test you need to make sure there is some initial content, create the saved search and then add something that meets the criteria, and then tell the system manually to look for new items for notification, and then check your email to see the item is emailed. This is a time sensitive operation and you may also want to make sure the notification system only runs on a daily basis and no more.

    Here, it would be easier to write an automated test. You can use mocks in a similar way to the way you use fixtures (mocks are to behaviour what fixtures are to data)....

    a simple test might look like....

    Code:
    class NotificationTest < Test::Unit::Testcase
      def test_emailer
        # Assume empty database, we generate our data here (I dislike fixtures personally)
        Time.is :year => 2005 do
          product = Product.create :title => "Playstation 2", :description => "This was vaugely successful", :price => 400.USD
          user = User.create :name => "Jase", :login => "miijase", :password => "<Insert random numbers and rude word here>"
          Time.is 1.week.since do
            user.saved_searches.create :min_price => 200.USD, :max_price => 500.USD, :title => "Comp00ters and stuff", :category => "Electronics"
            # Try and initate a email, because the search is just generated it should not send an email as previously created stuff does fit
            user.saved_searches.notifiy_changes_by_email
            assert_equal 0, sent_emails.size
            product = Product.create :title => "Playstation 3", :description => "This will be a flop, dont buy!", :price => 600.USD
          end
          Time.is 2.weeks.since do
            # No products added that fit criteria, so still no email
            user.saved_searches.notifiy_changes_by_email
            assert_equal 0, sent_emails.size
          end
          Time.is 3.weeks.since do
            product = Product.create :title => "Nintendo Wii", :description => "You know you want one, it saves going to the gym!", :price => 300.USD
          end
          Time.is 4.weeks.since do
            user.saved_searches.notifiy_changes_by_email
            assert_equal 1, sent_emails.size
            assert sent_emails.last.body =~ /Nintendo/
          end
        end
      end
      
      def sent_emails
        ActionMailer::Base.deliveries
      end
    end
    Note I've assumed there's some methods added to Integer (i.e. USD) which are used to automagically create currency / money objects. Also, I've assumed a "is" in Time, which can be used to overide / mock the value returned by Time.now. You can easily create one like this....

    Code:
    # For tests that require the 'mocking'/faking of the system clock
    class Time
      @@list = []
      cattr_reader :list
    end
    
    class << Time
      def now
        return list.last if list.last
        new
      end
      
      def flush
        list.clear
      end
      
      def is(time, &code)
        set time
        begin
          code.call if code
        ensure
          list.pop
        end
      end
      
      def resolved(time)
        return Time.utc(*time.values_at(:year, :month, :day, :hour, :minute, :second)) if time.is_a? Hash
        time
      end
      
      def set(time)
        list << resolved(time)
      end
    end
    The addition to the Time class I put in here I find is quite handy when testing event based things that need to be time sensitve such as this.

    As you can see, the test case is not that big considering. Testing manually probably a lot more time when you've had to do do it more than 1 or 2 times.

    If you design with testing in mind you will find you will write better code, because the process seems to implicitly make you make code more modular in a way that it's easy to substitute your code and data with fixed / mocked alternatives when testing.

    Remember those days of science experiements at school where you are supposed to test one variable at a time and you use a "control" in your experiement to compare against. Well testing is much like this, you are testing a one given aspect of your system at a time (much like science experiments test the change in one given 'variable'), and your control is much like the fixed data and mocks (fixtures etc, which are fixed so you have something to compare against).

    Obviously what I have put above is purely a unit test, and isn't a functional test, but it shows how you can avoid the chore of manual faffing in the browser. Proper Functional tests generally extend the idea further to make sure you get the right HTTP headers and content for given controllers. I tend to not rely on such high level test as much as you do need to do manual testing here to test for things like usablity anyway, so you can't totally escape manual testing, but you can certainly minimise it.
    http://virtualfunction.net - Rails Web Development
    http://squaremove.co.uk - Rails powered Property Listings


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •