Screw.Unit tests not displaying properly in IE

The Screw.Unit JavaScript BDD framework is awesome, I love it.  Unfortunately if you grab the current head from github, it comes down with jQuery 1.2.6.  Using 1.2.6 with Screw.Unit and trying to run your tests in IE will result in something like this:

image

when it should look like this:

image

Simply upgrade from jQuery 1.2.6 to 1.4.1 and the problem will go away:

image


Posted by: Jeff
Posted on: 2/19/2010 at 8:07 PM
Categories: jQuery | Testing
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (1) | Post RSSRSS comment feed

BDD renaming macro with VB.net support

UPDATED: The code below has been replaced on 2/5/2010.  The previous code wasn't working too well in in 2008 when the case of "public sub" changed to "Public Sub". An additional change, if the text on the line does not contain double quotes, the method will exit without changing your code.

The BDD renaming macro from Jean-Paul Boodhoo really reduces the friction in typing BDD style test names. I can't tell you how much I despise hitting _ so much.  Anyways, since I work in VB.Net and well as C#, I had to add VB.net support to the macro.  Just map this to a hotkey (I use Ctrl+Alt+-), and you're set. Why is this important? It's important because you can generally type "Should return 0 when the input parameter is 0" much faster than Should_return_0_when_the_input_parameter_is_0.

In C#, this:

public void "Throws an exception with invalid input"()
changes to
public void Throws_an_exception_with_invalid_input()
and in VB:
Public Sub "Throws an exception with invalid input"()

changes to

Public Sub Throws_an_exception_with_invalid_input()
 
 
The Code:
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics

Public Module CodeEditor
    Sub ReplaceSpacesInTestNameWithUnderscores()
        If DTE.ActiveDocument Is Nothing Then Return

        Dim selection As TextSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection)
        selection.SelectLine()
        If selection.Text = "" Then Return

        Dim prefix As String = "public void "
        Dim index As Integer = selection.Text.IndexOf(prefix)

        If index = -1 Then
            prefix = "public sub "
            index = selection.Text.IndexOf(prefix, System.StringComparison.CurrentCultureIgnoreCase)
            If index = -1 Then
                MsgBox("Could not find method identifier")
                Return
            End If
            prefix = selection.Text.Substring(index, prefix.Length)
        End If

        prefix = selection.Text.Substring(0, index) + prefix

        Dim description As String = selection.Text.Replace(prefix, String.Empty)

        If description.IndexOf("""") = -1 Then
            selection.EndOfLine()
            Return
        End If

        selection.Text = prefix + description.Replace(" ", "_").Replace("'", "_").Replace("""", "")
        selection.LineDown()
        selection.EndOfLine()
    End Sub
End Module

Posted by: Jeff
Posted on: 2/3/2010 at 1:21 AM
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

DataTable cannot equal DBNull

I've seen this a couple of times in code, so it's worth mentioning.  There seems to be some confusion around what DBNull is supposed to be used for.  DBNull is meant to test field values of a DataTable for a value of NULL.  If you're doing something like

If DBNull(myDataTable) = False Then
 ' do something with the DataTable
End If

Then you're setting yourself up for a possible exception. DBNull on anything other than a proper DataTable field will always return false.

Consider the following test

Imports System.Data
Imports NUnit.Framework
<TestFixture()> _
Public Class DBNullTest
    <Test()> _
    Public Sub CanDataTableBeIsDBNull()
        Dim dt As DataTable = Nothing
        Assert.IsTrue(IsDBNull(dt))
    End Sub
End Class

CanDataTableBeIsDBNull will fail because dt is a DataTable type and not a field value from the DataTable.  So if you have to check to see if a DataTable is a valid object after an operation to populate the DataTable, use a comparison with Nothing instead:

    <Test()> _
    Public Sub CanDataTableBeNothing()
        Dim dt As DataTable = Nothing
        Assert.IsTrue(IsNothing(dt))
    End Sub

Posted by: Jeff
Posted on: 1/17/2010 at 1:37 AM
Categories: VB.NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

When email notification is not working in ELMAH

Hopefully you've heard of ELMAH, (Error Logging Modules and Handlers) if you're doing ASP.NET work. This gem is priceless when trying to catch unhandled exceptions in your project.

I ran into an issue today when following the web.config guidelines in the elmah release (it contains a sample web.config with documentation for all the configuration).  I wanted to be emailed whenever an exception occurred on the site, so I put the appropriate settings into the errorMail element in the <elmah /> configuration.  I setup some test exceptions to make sure that ELMAH was working correctly, and could see the errors in elmah.axd, but the emails were not being sent.

It turns out that the modules registered under <system.webServer> <modules> need to be included in <system.web> <httpModules> as well:

<system.web>
<httpModules>
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
    <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"  />
</httpModules>
</system.web>

The example web.config mentions having to put these modules in additional modules in httpModules if mail reporting is desired, but since it was commented out in the example, I accidentally skipped over it.  After this change was made, the email notifications started coming through.  Hopefully this will help me remember in the future, or help someone who is having the same issue.


Posted by: Jeff
Posted on: 1/16/2010 at 12:13 AM
Categories: elmah
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Being careful with jQuery's bind() and introducing bindOnce

jQuery's bind() method is extremely useful. If you call $(myElement).bind('change',function(){...}) multiple times, you can chain multiple events on the same element.

$('a').bind("click", function() { alert('event 1'); });

$('a').bind("click", function() { alert('event 2'); });

These two calls will take all links on in your DOM and alert("event 1") and alert("event 2") when any of them are clicked. Fantastic!

However, there is the potential for an undesired side effect if you use bind unwisely.  For example, say you have a modal dialog popup in your application.  When you have to display the modal dialog, you perform some setup first:

   1:  function SetupModalDialog() {
   2:      $('select', '#dialogContainer').bind('change',function(){
   3:          alert('be careful what you wish for');
   4:      });
   5:  }
 

If for some reason you have to call SetupModalDialog multiple times (perhaps because some of the controls are dynamic based on other parts of the page), the drop downs will have this function bound to the change event each time this function is called.  What does this mean?  If you open your dialog twice, and change the selection on a dropdown in the dialog, you will see two alert windows saying "be careful what you wish for".

There are a couple of ways you can handle this situation. One would be to go back through the elements you've setup events on and call unbind. Having clean up code like this is ideal, but not always practical. Another solution which will minimize your code changes is to make sure you're not binding the same function more than once.

Introducing bindOnce

   1:  function bindOnce(element, event, handler) {
   2:      if (element === undefined || event === undefined || handler === undefined)
   3:          return;
   4:          
   5:      var jqueryObj = $(element);
   6:   
   7:      var events = jqueryObj.data('events');
   8:   
   9:      if (events === undefined) {
  10:          jqueryObj.bind(event, handler);
  11:      }
  12:      else {
  13:          if (events[event] === undefined) {
  14:              jqueryObj.bind(event, handler);
  15:          }
  16:          else {
  17:              var isBound = false;
  18:              $.each(events[event], function(i, eventHandler) {
  19:                  if (eventHandler.toString() === handler.toString()) {
  20:                      isBound = true;
  21:                      return false;
  22:                  }
  23:              });
  24:   
  25:              if (isBound === false) {
  26:                  jqueryObj.bind(event, handler);
  27:              }
  28:          }
  29:      }
  30:  }

bindOnce simply excepts and element, the event to handle ('click'), and the function to handle the event.  By using the jQuery.data("events") collection, we can determine if the event and function have already been bound to the element in question.

Of course what good reason is there to have a method to do the work that does not extend jQuery? None that I can think of, so here's the jQuery plugin:

(function($) {
    $.fn.bindOnce = function(event, handler) {
        if (event === undefined || handler === undefined)
            return;
 
        var events = this.data('events');
 
        if (events === undefined) {
            this.bind(event, handler);
        }
        else {
            if (events[event] === undefined) {
                this.bind(event, handler);
            }
            else {
                var isBound = false;
                $.each(events[event], function(i, eventHandler) {
                    if (eventHandler.toString() === handler.toString()) {
                        isBound = true;
                        return false;
                    }
                });
 
                if (isBound === false) {
                    this.bind(event, handler);
                }
            }
        }
    };
})(jQuery);

The usage is typical:

   1:  $('a').bindOnce('click', function() { alert('Hey...'); });

Enjoy.

Posted by: Jeff
Posted on: 1/12/2010 at 11:05 PM
Categories: jQuery
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

WPingF source released on GitHub

The source for WPingF is up on GitHub now.  Here's the link: http://wiki.github.com/codereflection/WPingF

Visual Studio 2010 Beta 2 and Windows 7 are required.  Visifire is distributed with the source for graphing capabilities.

If you would prefer just the binaries, they are available under Downloads on GitHub: http://github.com/codereflection/WPingF/downloads

Enjoy.


Posted by: Jeff
Posted on: 11/11/2009 at 9:36 AM
Categories: WPingF
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Turning your Lenovo W500 into a wireless router

Scott Hanselman (@shanselman) had a tweet today about an open source virtual router for WiFi sharing (http://virtualrouter.codeplex.com/) (via @crpietschmann). This reminded that before I upgraded to Win 7, I found that my Lenovo W500 (best laptop ever) had support in Vista for creating a personal WiFi network using the Intel adapter.  I dug a little deeper to see if this also works in Win 7.

The latest version of the Intel WiFi drivers (v13) do include support for Intel's My WiFi technology, which allows you to turn your laptop into a wireless router, allowing up to 8 computers to connect, while maintaining your wireless connection to the Internet. (BTW ' I downloaded the Intel 5150 drivers first, without realizing that I have the 5300, to find that the 5150 does not support this feature).

To do this, your W500 has to have either the Intel 5300, 5100, or 1000 WiFi adapter.

You'll have to download the large driver package from Lenovo (around 78 meg), and choose the custom install, because My WiFi support is not installed by default:

Installing Intel PROSet

After installation, you will find My WiFi under Intel PROSet Wireless

My WiFi Start Menu

You then have to enable My WiFi support:

Enabling My WiFi

There are a few options for adding devices, some supporting WiFi Protected Setup:

Add A Device

Manually adding a device though show a scary security passphrase:

Manually Add A Device

You can change this though by adding a new Profile:

New Profile

Adding a new profile allows you to set the SSID, security settings, etc:

New Profile - Name

It'll give you a really long encryption key by default, but you can change it here:

New Profile - Security

They'll even let you set the default channel:

New Profile - Channel 

Options will even let to change what DHCP settings it's going to use for your connected clients:

How well does it work? I don't know yet, once some of the other laptops in the house aren't being used, I'll try it out, (BTW, none of these settings are for my actual setup, so just incase you know where I live, this info won't help you). :)

 


Posted by: Jeff
Posted on: 11/10/2009 at 8:10 PM
Categories: W500
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (1) | Post RSSRSS comment feed

WPingF - A Windows 7 enhanced ping utility

Late last night I was copying a group of large files for an application deployment over to a server that exists on a very shaky and temperamental wireless internet connection.  My VPN connection would constantly drop, at least every 3 to 4 minutes.  A continuous ping is my friend here as it lets me know as soon as the server stops responding, but it's kind of a pain to have to resize my windows to see the command prompt all the time.

So I got to thinking about Scott Hanselman's post about apps that "Light Up" on Windows 7, and Scott's post about Jeff Key's Taskbar Meters. Wouldn't it be great to have a simple ping utility that would let me see the response time and timeouts via the Windows 7 taskbar?  Of course it would.

After 30 minutes or so (I know, but I had to get a drink of water), I had this little app thrown together, and so I have named it WPingF:

WPingF Interface

And of course the entire purpose of this is the taskbar status:

WPingF Taskbar Ping Status

The indicator is the roundtrip time / the specified timeout, and it will turn red when there's a response timeout.

WPingF Taskbar Ping Error Status

It's not much to look at right now, but it works.  I'm going to add a couple more features to it (such as saving the host names in the drop down in a local xml for thumb drive deployment), and stick the code out there for anyone who cares to abuse it.

(BTW - the WPF designer in VS 2010 is quite nice.  So much better than having to switch over to Blend or do everything in angle brackets)


Posted by: Jeff
Posted on: 11/2/2009 at 6:22 PM
Categories: WPingF
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (2) | Post RSSRSS comment feed

Visual Studio 2010 Debugging Coolness - Pinning variable watches

A new debugger feature in Visual Studio 2010 that I really love is pinning debugger views (basically a watch in a floating window) of variables:

Pinned Variables Setting Pin

So when you break into the code again, you won't have to hover back over the interesting variable, you just need to look at the pinned item.

Pinned Variables

You can even set a comment on the pinned watch:

Pinned Variables Comment

This allows you to pin multiple variables as well, from basically anything you could normally see in in debug view (as far as I can tell):

Pinned Variables Setting Second Pin


Posted by: Jeff
Posted on: 11/2/2009 at 7:06 AM
Categories: VS2010
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (1) | Post RSSRSS comment feed

Running tests from Visual Studio 2010 Beta 2, TestDriven.Net 3, and xUnit.net returns a FileLoadException

UPDATE: This issue is now resolved in TestDriven.NET 3.0.2556 (http://testdriven.net/download.aspx). Thanks to Jaime Cansdale (@jcansdale) for fixing this issue so quickly.

When you try to run TestDriven.NET 3 in Visual Studio 2010 Beta 2 with xUnit.net, you might get the following exception:

------ Test started: Assembly: Mylibrary.Tests.dll ------

=== ERROR IN TEST RUNNER: xUnit.net 1.5 build 1479 ===
System.IO.FileLoadException: Could not load file or assembly 'file:///c:\users\jeff\documents\visual studio 2010\Projects\MyLibrary\Mylibrary.Tests\3rdParty\xunit\xunit.runner.tdnet.dll' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)
File name: 'file:///c:\users\jeff\documents\visual studio 2010\Projects\MyLibrary\Mylibrary.Tests\3rdParty\xunit\xunit.runner.tdnet.dll' ---> System.NotSupportedException: An attempt was made to load an assembly from a network location which would have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET Framework does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for more information.

=================================================
It looks like you're trying to execute an xUnit.net unit test.

For xUnit 1.5 or above (recommended):
Please ensure that the directory containing your 'xunit.dll' reference also contains xUnit's
test runner files ('xunit.dll.tdnet', 'xunit.runner.tdnet.dll' etc.)

For earlier versions:
You need to install support for TestDriven.Net using xUnit's 'xunit.installer.exe' application.

You can find xUnit.net downloads and support here:
http://www.codeplex.com/xunit

To clear this issue up, you'll need to unblock the xunit reference dll's in the folder from which you're referenced them:

(do this for xunit.dll, xunit.dll.tdnet, and xunit.runner.tdnet.dll)

xunit.dll

Afterwards, you'll be able to successfully use TD.net again without this error. (I did not have the same issue with NUnit 2.4 however)


Posted by: Jeff
Posted on: 11/1/2009 at 11:21 PM
Categories: Testing | VS2010
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (5) | Post RSSRSS comment feed