Wednesday, May 24, 2006

The Ikea Breakfast

Mmmm yummers. Home fries. Probably formula-made scramble eggs. A couple breakfast sausages and a small croissant. 1 CAD$.


In case you didn't already know, Ikea has one dollar breakfasts. And they aren't bad! This past weekend, my wife wanted to get some supplies so we decided we would first try the breakfast before we went to the store to get our stuff. We headed to the North York store and arrived at about 9:30 on a Saturday morning. To our surprise the lower level parking lot was already about half full, to which I jokingly said "I bet they're all here for the $1 breakfast".

Well we got inside and the resturant was a zoo! There were two lineups, one on each side of the kitchen and people were lined up all the way back towards the seating areas. It didn't take very long waiting before we got our food, but when we did there was unfortunately no place to sit. We ended up sitting on a weird low couch and coffee table (ikea furniture of course).

When we finally went into the store, it was practically empty by comparison.

The coffee, by the way, is 99 cents per mug, free refills. It was pretty decent. They also have a sureshot machine for milk & cream just like Tim Hortons.

Friday, May 05, 2006

Game in the bag?



Check out the score in the lower right. Looks like Yahoo! jumped the gun. Link to actual box score of worse choke job ever here.

Thursday, May 04, 2006

aaaarrrrrrrgh

or a4r7gh.

What's your favourite permutation?

Sunday, April 30, 2006

Africa Calling

Africa Calling: "Burgeoning wireless networks connect Africans to the world and each other"

An interesting article on the state of cellular technologies in sub-Saharan Africa.

Thursday, March 23, 2006

NUnitAsp Upload File Tester

When I was working with NUnitAsp before, there was one part of my application that relied on a file upload control
. The page would parse the uploaded file and create some database objects based on the content of the file. Since the functionality of this page was critical to the operation of the site, it would be ideal to have some sort of test control to test file uploads. NUnitAsp, unfortunately, did not have any such support built in.

But alas, it was open source - so I made a few modifications. The result is my HtmlInputFileTester, which allows you to upload a file within an NUnitAsp unit test. This is the full NUnitAsp distribution with some small changes, in particular adding a control to test file uploads.

Using the control is easy. In your UnitTest, you can create a test object like this:

// There is an upload control with id/name = "file"
HtmlInputFileTester fileUpload =
new HtmlInputFileTester("file", CurrentWebForm, true);

// Specify the full path of the filename
fileUpload.Filename = "C:\MyFiles\MyFile.txt";

// And then click a button control as you normally would
submit.Click();


If the filename is left blank, then no upload will take place.

In order to get this to work, I had to modify the way that forms were submitted under the NUnitAsp HttpClient. Forms were orignally submitted using the Http content type "application/x-www-form-urlencoded". This method uses a query string type format of passing in all the form variables through the request body.

My modification uses "multipart/form-data" as the content type, and thus each form variable has its own section in the request body. This allows writing a serires of bytes as a form value, making file uploads possible. The only other change to the suite is adding the HtmlInputFileTester control, which recognizes file uploads in your ASP.NET HTML and allows you to submit a file within your tests.

The definitive reference for managing file uploads in browsers is supplied in RFC 1867.

Happy uploading!

Sunday, March 05, 2006

Is not nothing something?

This past week, I discovered that a type of SQL statement that doesn't work as I would expect it to. After thinking about it, I still can't decide if the Microsoft SQL Server is at fault, or if it was just the cause of a poorly formed query. The problem happens when a data set contains a mixture of null and not null data. Since the problem can be resolved with some crafty SQL scripting, I am leaning towards this more the fault of the query, but there are some interesting observations to be made of this.

The query at question is to select all the values to the exclusion of values in a second set. It looks something like this:

SELECT * FROM pet WHERE remark NOT IN (
SELECT remark FROM pet WHERE name='Fluffy' )

I may have modified the original query significantly (trust me I do not deal with pet databases at work!) but the gist of the query is the same. Here we are trying to get a list of all pets where the "remark" is not the same as Fluffy's remark.

This query works fine unless Fluffy's remark is null. When this happens, you would expect the query to be simplified to something like this:
SELECT * FROM pet where remark NOT IN (NULL)

which you think would select everything, but this doesn't happen. Instead SQL Server returns nothing at all. In this case, not nothing is nothing.

Out of curiosity, I tried building a similar query in MySQL to see how this database handles the request. Here, the output is different! We get 1 row back - Fluffy.

+--------+------+--------+--------+
| name | date | type | remark |
+--------+------+--------+--------+
| Fluffy | NULL | litter | NULL |
+--------+------+--------+--------+
1 row in set (0.00 sec)

The query was written in hopes of getting all not Fluffy remarks, and you end up getting either nothing, or you get Fluffy back. Not very helpful or consistent.

So how do we solve this to work properly? We need to handle our null values better. Basically we want to get rid of the null values we were working with, and to this we can use the ISNULL function. There are equivalents in both MySQL and SQL Server. For SQL Server, you can the syntax is IsNull(,) which substitutes the default value for any null values in the db. In MySQL, the function ISNULL() returns 1 if the column is null, and 0 if it is. To get the same effect, use a case statement in your syntax:
SQL SERVER

SELECT IsNull(remark, 'empty') remark FROM pet WHERE name = 'Fluffy'

MYSQL

mysql> SELECT CASE isnull(remark) WHEN 1 THEN 'empty' ELSE remark END remark FROM pet WHERE name = 'Fluffy';
+--------+
| remark |
+--------+
| empty |
+--------+
1 row in set (0.00 sec)


After the set query is modified to not use any null values, we can modify the whole query to exclude our empty set. And therefore, our full query below will finally get our expected results:

SQL SERVER

SELECT * FROM pet WHERE IsNull(remark,'empty') NOT IN (
SELECT IsNull(remark,'empty') FROM pet WHERE name='Fluffy' )

MYSQL

SELECT * FROM pet WHERE CASE isnull(remark) WHEN 1 THEN 'empty' ELSE remark END NOT IN (
SELECT CASE isnull(remark) WHEN 1 THEN 'empty' ELSE remark END FROM pet WHERE name='Fluffy' )


It's ugly but it works!

Thursday, February 16, 2006

Some fun with NUnitAsp

I've started using NUnitAsp to do some tests for an ASP.NET program at work. It's a pretty neat little tool that allows you to build unit tests for your web pages. If you've ever used JUnit or NUnit before, this actually uses the same concept, but instead of testing a class, you write tests for your .aspx page.

How it works:

The testing is done by automating actions that a web user would do, such as entering text, selecting drop downs, and clicking buttons. You can build your tests in a new DLL project that doesn't reference any of your actual code behind. Each web page can have it's associated test class. To run the tests, you load the DLL using your NUnit-Gui (you do use NUnit right?) and just run it like any other test suite. It then goes through all your test methods and shows either passes or failures.

Most of the built in System.Web.UI.WebControls ASP.NET controls are supported, as well as some of the HTMLControls. You can manipulate all these controls programatically in your unit tests, just as you would in a web browser. You can insert text into text boxes, select drop downs, and click buttons and links, and test to see that the desired results are displayed on the next page refresh.

What you can test:

Before you jump into NUnitASP, first you should know what it is and is not capabale of doing. Each test case inherits the Nunit Assertion class, so all NUnit assertion methods can be used. In addition, there are four different types of WebAssertions specific to testing ASP pages, three which are helpers for dealing with string arrays (for data grids), and AssertVisiblity. This last one is probably the most important, since it applies to every test control. You can use it to test the dynamic display of your web controls.

Also, all the properties of the test web controls are available to be tested. This includes whether they are enabled, their value, and other properties that are part of the underlying HTML code.

Other things you can test are the browser properties, such as the current URL (for form redirection), and the raw HTML if there is anything else you want to test that isn't provided in the framework.

What you can't test:

The support for HTMLControls is pretty much non-existant. This includes uploading files, hidden inputs, and other still useful objects that didn't make the Microsoft's WebControl cut.

The browser also doesn't perform javascript. This can be a bit of a pain, since this means that some of your validation may not work. (But you don't need to worry about this because you are using post back validaton too, right?). So don't even bother using this to test your AJAX applications. I should emphasize that NUnitAsp is primarily for testing code behind, and not the client-side display magic.

The combination of these two don't-haves can cause trouble for many web applications. The application I was working on used javascript on the Login Form page. Basically, it was performing a hash algorithm on the password before sending it to the server because the client didn't want to use https. The algorithm also relied on hidden inputs to transport the encrypted data. In order to get this app to work with NUnitAsp, I basically had to copy the javascript encryption code into the NUnitAsp test classes, and perform the hash before assigning it to the text box. And since there is no support for hidden fields, I used a TextBox of width zero to store the encrypted value. After these changes, the automated login worked fine and I could continue writing other tests.

How it really works:

Every ASP.NET control that you plop onto your web page has an ID that you can customize. NUnitAsp's browser parses the HTML from your web page, and is able to determine the controls that you placed on your page, based upon those IDs and other features.

LinkButtons are a little different. If you notice the generated HTML of your pages, you will see that when you click a link button, it actually calls the following:
javascript:__doPostBack('lnkButter',''). Well when I said before that their WebBrowser had no javascript support, I kind of lied. There is support for this command, which I believe is interpreted within (instead of actually executing the javascript). This javascript function adds the following POST arguments to the form submit:
  • Request.Form["__EVENT_TARGET"] = "lnkButter"

  • Request.Form["__EVENT_ARGUMENT"] = ""


The order they are added through the NUnitAsp Browser is a little different than Internet Explorer though which actually caused me a little problem when I was looking for a link name in Request.Form[0] and couldn't figure out why my test case kept on failing whereas it always worked fine in ie. In retrospect I shouldn't have been so lazy and should have used the proper key, but I reported this as a potential bug just in case.

When you should use it

From my experience, NUnitAsp can help you most if you have a suite of tests early in the development cycle, and anticipate there to be changes in the underlying structure.

For example, the application I was working on had a dependency on underlying Business objects and Data Access objects that were generated on the database schema. Every week or so the client would request a new feature or a change to the feature which cause a change to the database schema. Once the objects were regenerated, and the UI code was modified to compile, sometimes trying to access web pages would crash because they were depending on fields that no longer existed, or more often they were not setting values that they should have been. A suite of simple NUnitAsp tests can catch these failures right away.

Another reason where NUnitAsp tests are handy is when you have a lot of dynamic display controlled by code behind. If there are multiple panels, buttons disappearing or disabling, form editing, submitting, and in general lots of actions going on, it really helps to have a set of tests for each action to ensure that the correct items are displayed before and after. I find it's always possible to forget to refresh the state of controls after performing an action, so a set of tests will help you find these and maintain sanity on complex pages.


When you shouldn't use it

More importantly, knowing when not to use NUnitAsp could save you many hours of wasted development.

As I mentioned before, there is no javascript support so if you have lots of client-side code doing calculations and other logic, you may have to replicate all this code within your unit tests. You would also have to convert the code from javascript to C# which is no easy task in itself. I would avoid testing pages with lots of javascript for this reason.

Also, if your pages are simple, then it probably isn't worth the time to build an entire unit test for the functionality. Say the page is for registration - a bunch of fields that you collect, validate, and store in a database and never touch again. This is an example where a unit test may not be necessary since there aren't any dynamic factors in play. It doesn't hurt to build one, but if you only have time to build so many tests, this is the type of page I would add last.

If your site is small, then again manually asserting functionality is probably the best option. NUnitAsp works best when there are many pages to keep track of with shared code. Making one change can often cause problems somewhere else. When pages are small or isolated, you get less value from using NUnitAsp.

Another obvious thing to mention is that you must be able to automate your web pages. If your site has some control that displays an image with text that the reader has to enter into a text box, you won't be able to run an NUnitAsp test on this (unless you only want to test failures.)



I hope I have given a good overview how you can use NUnitAsp to enhance your development process. In the next week I will give a list of tips for developing NUnitAsp, that should make it even easier to integrate into your current project.