Anagrams can bite back !!!

datePosted on 13:11, June 28th, 2006 by Peter Fitzgibbons

Jim’s article demonstrates this :
Don’t say CRUD say FUC’D.

I Love It!

categoryPosted in Uncategorized | commentsNo Comments | moreRead More »

Coverage (rcov 0.5.0.1) in Ruby on Rails 1.1.2

datePosted on 13:09, June 1st, 2006 by Peter Fitzgibbons

rcov 0.5.0.1: code coverage for Ruby released by Mauricio Fernandez contains all that is needed to produce code-coverage reporting in Rails.

Requirements

Ruby 1.8.4 (especially on Win32 requires updated libraries.)
Rails 1.1.2

Classes

There is only one file to add to your current rails app: lib/tasks/coverage.rake

require 'rcov/rcovtask'

namespace :test do
  Rcov::RcovTask.new do |t|
    t.libs << “test”
    t.test_files = FileList['test/unit/*.rb', 'test/functional/*.rb']
    t.output_dir = 'test/coverage'
    t.verbose = true
  end
end

Rake -T

Here’s the new tasks with rake -T :

(in C:/radrailsworkspace/pimki/trunk)
[... snip standard tasks ...]
rake test:clobber_rcov         # Remove rcov products for rcov
rake test:rcov                 # Analyze code coverage with tests
[...]

The default taskname for the RcovTask instance is ‘rcov’. Rcov automatically creates the ‘clobber_’ task that is basically a rm_rf on the RcovTask#output_dir.

Cover it

Run rake test:rcov and see how much of your code is really tested!!

Report Coverage

The end of your rake run will contain a pretty-print text report of the rcov. Also, you can navigate to ./test/coverage/index.html to see the graphic report. See the docs for more info.

categoryPosted in Uncategorized | commentsNo Comments | moreRead More »

Single Fixtures declaration for Selenium on Rails

datePosted on 12:58, March 29th, 2006 by Peter Fitzgibbons

When testing out a complex website, replicating the |open|/selenium/setup?fixtures=x| line would be painful!

So, Add a const at the beginning of the setup_controller in Selenium Plugin at
./vendor/plugins/selenium_on_rails/lib/controllers/selenium_controller.rb:

MY_FIXTURES = “table_a, table_b, table_c”

Also alter #setup as so :

def setup
    unless params.has_key? :keep_session
      reset_session
      @session_wiped = true
    end
    if params[:fixtures] == “all“
      fixtures = PM_FIXTURES
    end
    fixtures ||= params[:fixtures].to_s
    @loaded_fixtures = load_fixtures fixtures
    render :file => view_path('setup.rhtml'), :layout => layout_path
  end

New lines are 6-9, and the change on 10 from referencing params[] to the local var fixtures.

Then, use this in the selenese script :

|open|/selenium/setup?fixtures=all|

Isn’t that beautiful!??

Now I don’t have to endure copy-paste-age-break hell on my fixtures configuration.

Ahhh, Ruby is so nice!

categoryPosted in Uncategorized | commentsNo Comments | moreRead More »

Mr Yuk Happy 35th!

datePosted on 08:34, March 22nd, 2006 by Peter Fitzgibbons

This is Poison Control Week, Mar 19-25, 2006. Since Mr. Yuk was conceived in 1971, this makes it Mr. Yuk’s Birthday!

Poison Prevention.org

categoryPosted in Uncategorized | commentsNo Comments | moreRead More »

1 – Strategy Pattern

datePosted on 10:11, March 14th, 2006 by Peter Fitzgibbons

The Strategy Pattern really resolves to “composition” in practice. This OO technique says to take components that could change at runtime and encapsulate them in their own objects. The master-object is then “composed” of instances of the dependent clasess.

Example:

class Duck
  def fly
    puts ‘Flap Flap’
  end

  def quack
    puts ‘Quack!’
  end
end

d = <span class="constant">Duck.new
d.flap
d.quack

Produces:

Flap Flap
Quack!

So now handle the en-user request to have ducks with different flap :

class FlapWings
  def fly
    puts ‘Flap Flap’
  end
end

class FlapSoaring
  def fly
    puts ‘Soaring in the wind’
  end
end

class Duck
  def initialize (flapInstance)
    @flapDelegate = flapInstance
  end
  def changeFlap(flapInstance)
    @flapDelegate = flapInstance
  end
  def fly
    @flapDelegate.fly
  end

  def quack
    puts ‘Quack!’
  end
end

mallard = Duck.new(FlapWings.new)
mallard.fly
mallard.quack
mallard.changeFlap(FlapSoaring.new)
mallard.fly

Now produces :

Flap Flap
Quack!
Soaring in the wind

This example looks trivial. The technique is powerful. Behold that in Java/C#, this requires a lot of effort including Inheritance and Interfaces.

Nice that Ruby allows this run-time change through duck-typing!!

categoryPosted in Uncategorized | commentsNo Comments | moreRead More »

Unit Test WPF Window with NUnit

datePosted on 08:13, February 24th, 2006 by Peter Fitzgibbons

I will outline how to setup NUnit testing with WinFX 1.0 (Feb CTP) in order to UnitTest an Avalon Window.

What’s wrong

Points of technology that drive the details.

  • WPF windows must run on an STA Thread (Single-Apartment) MS Forums
  • NUnit (and TestDriven.net, using the NUnit API) run all tests with an MTA Thread. NUnit Developers Wiki: ExceptionsOnThreads
  • In order to generate and start an STA thread from within a running MTA, grasshopper, you must warm up your System.Threading fu and investigate Thread() and Thread.SetApartmentState. GeekNoise : Peter Provost

The recipe to success

  1. Create a new class in your test Assembly to hold the NUnitHelper namespace and class.

    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Security.Permissions;
    using System.Threading;
    using System.Text;
    
    namespace NUnitHelpers
    {
        class CrossThreadTestRunner
        {
            private ThreadStart userDelegate;
            private Exception lastException;</p>
    
        public void RunSTA(ThreadStart userdelegate)
        {
            this.userDelegate = userdelegate;
            Thread t = new Thread(new ThreadStart(this.MultiThreadedWorker));
            t.SetApartmentState(ApartmentState.STA);
            t.Start();
            t.Join();
    
            if (lastException != null)
            ThrowExceptionPreservingStack(lastException);
    
        }
    
        public void Run(ThreadStart userdelegate)
        {
            this.userDelegate = userdelegate;
            Thread t = new Thread(new ThreadStart(this.MultiThreadedWorker));
            t.Start();
            t.Join();
    
            if (lastException != null)
                ThrowExceptionPreservingStack(lastException);
    
        }
    
        [ReflectionPermission(SecurityAction.Demand)]
        private void ThrowExceptionPreservingStack(Exception e)
        {
            FieldInfo remoteStackTraceString = typeof(Exception).GetField("_remoteStackTraceString",
                BindingFlags.Instance | BindingFlags.NonPublic);
            remoteStackTraceString.SetValue(e, e.StackTrace + Environment.NewLine);
            throw e;
        }
    
        private void MultiThreadedWorker()
        {
            try
            {
                userDelegate.Invoke();
            }
            catch (Exception e)
            {
                lastException = e;
            }
        }
    
        }
    }
    

    This is adapted from Peter Provost’s original code. First, I compressed his constructor/method calls into just the method call. This allows me the cleanest calling-code that I can get with minimal effort. Second, I duplicated Run() into RunSTA() in order to test STA threads that are executing the WPF Window.

  2. Now my calling class (the actual NUnit testing class) can use this new helper to correctly process WPF testing (handling Assert exceptions instead of raising UnhandledException error inside NUnit’s execution path.) :

        using System;
        using System.Collections.Generic;
        using System.Text;
        using System.Threading;
        using System.Windows;
        using System.Windows.Automation;
        using System.Windows.Interop;
        using NUnit.Framework;
    
        namespace NunitTest
        {
            [TestFixture]
            public class Class1
            {
                NUnitHelpers.CrossThreadTestRunner runner = new NUnitHelpers.CrossThreadTestRunner();
    
                [Test]
                public void truthtest()
                {
                    Assert.IsTrue(true);
                }
    
                [Test]
                public void falsetest()
                {
                    Assert.IsTrue(false);
                }
    
                public static void TestAddressbookWorker()
                {
                    Window ab = new AddressBookLib.Window1();
                    ab.Show();
                    ab.Close();
                    ab = null;
                    Assert.IsTrue(false, "Forced NUNit Failure");
    
                }
    
                [Test]
                public void TestAddressBook()
                {
                    runner.RunSTA(new ThreadStart(TestAddressbookWorker));
                }
    
            }
        }
    

    Here each test method requires a worker that contains the actual testing code. The calling test is simply delegating the worker method into the CrossThreadTestRunner instance. Using RunSTA() starts an STA thread and then the WPF window is started happily.

  3. NUnit Output!! (For those unbelieving)
------ Test started: Assembly: NunitTest.dll ------

TestCase 'NunitTest.Class1.falsetest' failed:
    C:\Visual Studio 2005\Projects\WinFX\AddressBook\NunitTest\Class1.cs(26,0): at NunitTest.Class1.falsetest()

TestCase 'NunitTest.Class1.TestAddressBook' failed: Forced NUNit Failure
    C:\Visual Studio 2005\Projects\WinFX\AddressBook\NunitTest\Class1.cs(35,0): at NunitTest.Class1.TestAddressbookWorker()
    C:\Visual Studio 2005\Projects\WinFX\AddressBook\NunitTest\CrossThreadTestRunner.cs(55,0): at NUnitHelpers.CrossThreadTestRunner.MultiThreadedWorker()
    C:\Visual Studio 2005\Projects\WinFX\AddressBook\NunitTest\CrossThreadTestRunner.cs(48,0): at NUnitHelpers.CrossThreadTestRunner.ThrowExceptionPreservingStack(Exception e)
    C:\Visual Studio 2005\Projects\WinFX\AddressBook\NunitTest\CrossThreadTestRunner.cs(24,0): at NUnitHelpers.CrossThreadTestRunner.RunSTA(ThreadStart userdelegate)
    C:\Visual Studio 2005\Projects\WinFX\AddressBook\NunitTest\Class1.cs(42,0): at NunitTest.Class1.TestAddressBook()

1 passed, 2 failed, 0 skipped, took 21.25 seconds.
categoryPosted in Uncategorized | commentsNo Comments | moreRead More »

Nice to know I still remember something.

datePosted on 08:12, February 24th, 2006 by Peter Fitzgibbons

You Passed 8th Grade Math


Congratulations, you got 10/10 correct!
categoryPosted in Uncategorized | commentsNo Comments | moreRead More »

To Elena

datePosted on 08:11, February 24th, 2006 by Peter Fitzgibbons

Dan and Kim Steinberg have had a terrible loss of their daugter Elena.

Dan’s thoughts are here.

Kathy Sierra’s note

categoryPosted in Uncategorized | commentsNo Comments | moreRead More »

Use AJAX for onchange of a SELECT box

datePosted on 08:04, February 2nd, 2006 by Peter Fitzgibbons

Here’s how to use AJAX from the onchange event of the SELECT element :

I used an extra ERB step in my view in order to reduce chaos being created by double quotes. This example actually triggers two AJAX calls on the event to update different targets (two cascaded SELECTs).

<% onchange_ajax = remote_function(:update => :model_select,
                    :url => { :action => :ajax_list_model_select },
                    :with=> " 'project_id='+value") + ";" +
                 remote_function(:update => :category_select,
                    :url => { :action => :ajax_list_category_select },
                    :with=> " 'project_id='+value")
                 %>

<%= select("project", "id", @projects,
    { :include_blank=&gt;true },
    { :o nchange => onchange_ajax } ) %>

The result has the SELECT element with onchange=”new Ajax.Updater…”

Joy!

categoryPosted in Uncategorized | comments2 Comments | moreRead More »

Happy Coding or Status Quo

datePosted on 07:53, January 20th, 2006 by Peter Fitzgibbons

… This presentation brought to you by Brains on Trains—The leading supplier of hosed-up thought processes.

Ok. Spent too big of a portion of last year FIGHTING with Micro$oft VS .NET 2003/2005 and trying desperately to show that my dying VB6 apps can be converted to them. Well, conversion doesn’t work, at least on my KLOC applications with major hacks embedded for unit testing and robust error handling.

Found the Rails in Feb 05 and basically “didn’t look back”. It took ‘till Nov 05 to get approval for the first app, and we were desperate. Success rate on that was HIGH as my off-the-cuff estimate “It’ll take 1 to 2 months” was right on target. Deployed critical-features version of app for public consumption at end of Nov. and then deployed final feature-rich (to the level that this rewrite needed) at end of Dec. Managers happy. Uesrs happy. Application admins (tech-support staff) happy. CODER HAPPY

I can’t say I”ve ever felt “Happy” coding in M$ anything. Always a catch, always a missing feature. Always a black box to deal with. Always some reason to spend 2 days googling and searching M$ forums for obscure answers.
Also, no support, unfriendly forum users, unhelpful forum “experts”.

I continue to hash around the balance between the pros and cons of this argument. It seems really clear on paper which is the better choice for continuing development… UNTIL the emotional ties to employer-loyalty, cost conciousness, time conciousness (both calendar time and timecard time) all get in the way. I have also voiced the concern to coworkers that with all the money M$ uses for VS development… how can it NOT be better??!!

In the final analysis, M$ CAN “not be better”. The 800lb Gorilla has lots of hair to shed and leaves a VERY large footprint.

With Ruby and Rails, my experience in learning curve was that the curve was low and short. Peaking the hill of learning these technologies was manageable, doable. Even without learning how to flex the technologies (I still don’t grok the metaclass), I have been able to overcome some serious design hurdles with the convenient flexibility of Ruby and the Rails framework.

Looking up, I notice ONE bolded phrase

CODER HAPPY

The reference… Ruby and Rails.

Hm..

I have an approved rails app to work on.

coder team alpha Out!

categoryPosted in Uncategorized | commentsNo Comments | moreRead More »
1234PreviousNext