NUnit tolerance on double arrays

Yesterday I wanted to compare two arrays of doubles in a unit test to make sure I didn’t change some resulting calculations when refactoring.

var expected = new double[] { 1.00000000000000006 , 2.00000000000000005 ,
3.00000000000000008 , 4.00000000000000007 , 5.0000000000000005 };
Assert.AreEqual(expected, process.GetResults());

It turns out that when I printed my expected results to get these constants, my print statement rounded them down to the displayed 15 decimal places. Rather than go print a longer constant to be used in my test, I wanted the ability to test within a given threshold.

It wasn’t until today that I decided to dive into NUnit and implement the needed methods when I browsed the NUnit source and discovered that this functionality already exists. The key is using the correct method overload. the above ends up with no overload. Indeed any arrays passed end up calling to Assert.AreEqual(object,object…) style overloads.

The answer is simple: use NUnit’s Constraint Model assertions.


Assert.That(expected, Is.EqualTo(process.GetResults()).Within(0.0000000001));

Works great! Thank NUnit!

I wish it were obsolete

Sometimes when dealing with legacy code (as in code with no unit tests which cannot be refactored easily), you run into cases that you wish were obsolete. The .NET Framework has a nice attribute called ObsoleteAttribute. You can put it on any members of your types, or even entire types and the compiler will let you know when this “obsolete” member is used. Its like a usage finder for people who don’t have CodeRush’s awesome Find All References feature.

Well, I recently ran across a case where I had to remove an ObsoleteAttribute because while I really wanted it to go away, I found out a case where it wasn’t so easy to remove it. I’m just not quiet ready to put in the work to refactor to the point I can call this property obsolete. So I’m proposing an IWishItWhereObsoleteAttribute.

public class IWishItWereObsoleteAttribute : ObsoleteAttribute {
public IWishItWereObsoleteAttribute(string reason) : base(reason)
{ }
}

But alas, my hopes and dreams are crushed by the creators of the framework

Error 1 'IWishItWereObsoleteAttribute': cannot derive from sealed type 'System.ObsoleteAttribute'

Major bummer.

C# has duck typing

C# 2.0 has duck typing.

No really, I swear!

Krzysztof Cwalina has a post on Duck Notation which I find very interesting.

Normally in .NET and thus C# to iterate you would use IEnumerable. You can call GetEnumerator yourself and call MoveNext from the implemented IEnumerator interface on the returned IEnumerable. Or 99 times out of 100 you use foreach.

The foreach operator in C# doesn’t use IEnumerable. I was so curious I just HAD to try it.

List<string> list = new List<string>(); 
foreach (string item in new C()) { 
	list.Add(item); 
} 
public class C { 
	public E GetEnumerator() { 
		return new E(); 
	} 
} 
public class E { 
	int x = 0; 
	string[] values = { "hello", "world", "foo", "bar", "baz" }; 
	public bool MoveNext() { 
		return x < values.Length; 
} 
	public string Current { 
		get { return values[x++]; } 
	} 
} 

Neither IEnumerable nor IEnumerator are used here, in fact IEnumerator would require the Reset method to be implemented. It is not present here. (Even though Reset is only there for COM interop and often just throws NotSupportedException, it is at least there.)

Also interesting is that there IS some type checking here. If you make the Current property of type object you get no type checking and in this case you would get a runtime InvalidCastException if you tried to add the result to a List<SomethingNotString>.

Is this useful? I don’t know. Maybe in edge cases. I still like IEnumerable<T> and with the extension methods coming in .NET 3.5 I REALLY want IEnumerable<T> to be a lot of places that it might not be if the above were used extensively.

The biggest problem with C# 3.0 is that it isn’t out yet. The second biggest problem with C# 3.0 is that the language features enable use of awesome things in .NET 3.5 and it isn’t out yet either. The third biggest problem with C# 3.0 is that all those awesome .NET 3.5 things need to be distributed so rollout of Framework 3.5 to servers and desktops might discourage your average organization from using an awesome piece of technology.

CI Factory with Subversion in a custom path

The CI Factory docs are pretty good, but being a first timer (ci factory noob!), I struggled a bit with this.

I found this FAQ entry which says to modify files in an already installed CI Factory project directory. It was easy enough to find CCNetServer.Bat in my Default directory that came in the CI Factory zip file, but the run.bat script was still failing.

It turns out that Nant needs the path to your svn.exe (well, of course it does!) and that everything CI Factory defaults to finding things in c:\Program Files\Subversion\bin. Well I don’t keep my SVN there. I keep it in c:\devtools\svn-win32-1.4.3\bin. Just add a PATH statement to the top of your run.bat script.

I gave my run.bat a nice little header that looks like this:

PATH=%PATH%;c:\devtools\svn-win32-1.4.3\bin

cd “c:\devtools\CI Factory”

The cd is because CI Factory’s run.bat (main install script) likes to setup IIS stuff. That is neato in a foolish Windows environment where you run as admin, but not so great when you aren’t running as admin and thus can’t modify IIS configuration. Not to mention I don’t even haven IIS installed!

It was at this point that I browsed my SVN tree again and noticed that CI Factory ACTUALLY WRITES BACK TO MY SCM!!! This is completely unacceptable and what is worse is that I didn’t read it ANYWHERE in the Installation or Introduction documentation. This is the kind of behavior which should have HUGE all upper case read warning text!

So much for CI Factory. I guess Its CC.NET manually for me.

Re: Defining Open Source

Jeff Atwood has a post about the definition of open source with respect his contributions to the .NET open source ecosystem.

I’m really glad that he brought this up because it has been on my mind for a while and based on his comments I can see there is MUCH confusion. I’m not going to address the confusion between “Open Source” as defined by OSI (The Eric Raymond definitions) and “Free Software” as defined by GNU (The Richard Stallman definitions). The commenters should read up as there is much writing on the differences here.

The confusion that I realized only as recently as January at CodeMash is that there are a number of closed source project out there that release their closed source under an open source license. Before you call this nonsensical please consider their development model. The source repository is closed. There are no public developer email lists. There is no public discussion of direction and upcoming features and who is implementing new features or even who is fixing big bugs before the next release. The Project is closed. However, every 6 months or every so often the source code is released and when it is it is under an open source license.

I’ll refrain from poking holes at this and calling this an abomination of the spirit of open source. The two aforementioned big names of Free Software and Open Source have plenty of writing on why this might be bad. The reality is that these projects exist and they are what they are. The project which opened my eyes to this model is DotNetNuke. This is a closed project which releases its code under an Open Source license.

Contrast this project with any open source project such as Mono or CastleProject and look at the surrounding communities. The core developer community exists. You know who they are. You can read public email lists. You can even chat via IRC with the folks who write the software. You can file bugs and submit patches. You can, you can, you can. DotNetNuke on the other hand does have a thriving community but it is all around writing plugins. Yes, you could download the source to the latest DotNetNuke release and you could change it all you want, but if you implement awesome new feature X, there is no where to submit it. If you fix annoying bug Y, you have to email it to a black hole and hope that the patch you made against last release will merge with their current private trunk.

In my opinion it is important to make the distinction between Open Source Projects and Open Source Software. All Open Source Projects by definition are Open Source Software, but Open Source Software might be a closed project. If the trunk is closed, how open is the software really? I’d say it is not open.

Jeff made the distinction in his post and has said he will be giving to Open Source Projects and not giving to closed projects that release their source under an Open Source license. I think this is great. Jeff recognized the distinction and is voting with his contributions.

On a lighter note, I couldn’t resist the Simpsons Movie character generator. The blowfish shirt seemed the geekiest to me.

simpsons avatar

Python davclient+PIL => my gallery uploader

Vista Vista Vista. Oh how you hate me.

It turns out the XP “Publish and Print” wizard – or whatever it was called – integrated great with Gallery just by adding a simple registry key and enabling the right Gallery add-ins. Vista doesn’t have this. Vista has instead a lame f-spot rip-off (ok, it is probably an iPhoto rip-off) called Windows Photo Gallery. It isn’t bad. It isn’t great. The XP publish wizard allowed me to resize images before sending them to an internet printer or Gallery. WPG doesn’t allow this. It turns out I can use the same Gallery reg and change just the registry path and it will work with WPG. But Gallery has a file size limit of two megabytes. I shoot my Canon S3 IS on its “SL” image setting so the file size is usually three or four megabytes.

Print and Publish and WPG doesn’t work for my case in Vista, so I’ll try WebDAV. I should just be able to “add a new network place” like in XP and type in the Gallery URL and then just drag and drop files (once they are resized of course). This is also a no go. It turns out that Microsoft is WAY smarter than me. Vista has disabled the ability to use WebDAV over HTTP. It can ONLY be used over HTTPS. Never mind that I don’t care about my plain text password in this case. It doesn’t matter. Vista is smarter than me.

Unwilling to manually resize and upload even a handful of files, I decided to script my solution. With only six hours until the MichiPug meeting I thought it would be fitting to use Python as my tool of choice. The bonus to using Python is that the solution will also run in Linux and since all of my Photos are stored on a Linux server running Samba, I’ll be able to publish photos remotely via ssh from my server if I want to (and if I happen to know the filename I want to publish).

It turns out resizing images easy trivial in Python thanks to PIL(Python Image Library).

import Image
width=1600
height=1200
imageFile="path/to/IMG_0100.JPG" im1 = Image.open(imageFile)
im5 = im1.resize((width, height), Image.ANTIALIAS)

tempdir = tempfile.gettempdir()
filename = os.path.basename(imageFile)
tempfilelocation = os.path.join(tempdir,filename)
im5.save(tempfilelocation)

So resizing the image was easy. Getting a filename from argv[1] was easy. I wasted a few hours barking up the wrong tree with davclient. Ultimately it was my own fault for not opening the file with ‘rb’. On Windows that ‘b’ matters! I’m used to python development on Linux where it is a meaningless.

At the end of the day I have a cmd script in my Send To folder that calls this python script

#!/usr/bin/python

import Image
from sys import argv
import tempfile
import os
import davclient

#site must include trailing slash
site = 'http://www.wrenfam.com/gallery/w/SomeGallery/'
username='myusername'
password='mypassword'
width=1600
height=1200

def imageTempResize(imageFile,width,height):
        im1 = Image.open(imageFile)

        im5 = im1.resize((width, height), Image.ANTIALIAS) # best down-sizing fi
lter
        tempdir = tempfile.gettempdir()
        filename = os.path.basename(imageFile)
        tempfilelocation = os.path.join(tempdir,filename)
        im5.save(tempfilelocation)

        return tempfilelocation

def davUpload(tempName, site, username, password):
        client = davclient.DAVClient(site)
        client.set_basic_auth(username,password)
        fname = os.path.basename(tempName)
        file = open(tempName,'rb')
        statinfo = os.stat(tempName)
        fsize=statinfo[6]
        url = site+fname
        contents = file.read(fsize)
        if len(contents)!= fsize:
                return

        client.headers['Content-Type'] ='application/octet-stream'
        client.headers['Content-Length'] = len(contents)
        client.put(url,contents)
        status = client.response.status
        if status==204 or status==201:
                print "file %s uploaded successfully" % fname
        else:
                print "something went bad when sending :( "
                print "client.put(%s,f=%s)" % (url, file)
                print status
                print client.response.getheaders()
                print client.response.body

for i in range(1,len(argv)):
        tempName = imageTempResize(argv[i], width, height)
        davUpload(tempName, site, username, password)

Now I can upload images just by clicking. Of course two big todos are to copy exif data. PIL has no support for writing exif data. pexif is in the cheese shop. It will get done. The second big todo is to support choosing to which to upload.

crying Lily

Open Source and .NET Software

Phil Haack has a great post on .NET and Open source software. It mirrors a lot of my own feelings. Thanks for expressing my feelings for me Phil!

One thing that I don’t agree with is my personally preferred platform. WISC (Windows, IIS, Sql Server, C#) is nice and all, but I really like it when my C# runs on Mono and that means Linux is an option and Apache is an option. I use NHibernate and Castle’s ActiveRecord and I avoid writing real SQL. That means I’m not tied to SQL Server. I can run the same code on SQL Server, SQLite, MySQL, PostgreSQL, Oracle, DB2, and probably some others thanks to HQL and NHibernate Drivers and Dialects. So I guess my platform of choice is [Windows|Linux] [IIS|Apache] [SQL Server|PostgreSQL] [C#] or just [WL][IA][SP][C], WLIASPC.  Pronounced “Will I asp see”. I guess.

Webforms attempt to abstract away something simpler

I’ve heard many people talk about how Webforms have problems, that the problems stem from being a leaky abstraction. I tend to agree, but I could never communicate the problem as succinctly as Jeff Perrin just did.

Now the first problem with Webforms is not that it’s an abstraction, or even that it’s a leaky one (they all are). The problem is that what Webforms attempts to abstract away is actually simpler than the abstraction!

The more I think on this the more it blows my mind! When you look at Html over Http and even CSS and JS, the whole system is REALLY SIMPLE! Maybe too simple, yes, but that is for what various helpers like Yahoo’s UI library are. Of course, I found this link while reading Ayende. 🙂

ASP.NET on Mono with Postgresql

Until bug 81490 was closed, Mono wasn’t capable of the ever popular “YOU DID IT WITHOUT ANY CODE” demo using Postgresql. For the unfamiliar, this is when someone demos Visual Studio’s ASP.NET designer and drags a table from the expanded database connection and drops it to the ASP.NET designer. The tool creates a connection string in the application configuration file, an SqlDataSource which uses the connection and a GridView which uses the SqlDataSource.

This code worked with Mono only if you were using SqlClient data provider. This means you were talking to Microsoft SQL Server. Most Mono users are on Linux. They want to talk to Postgresql or MySQL. Npgsql has an ADO.NET 2.0 provider model compatible library unreleased in source repository.

I’m of the opinion that declarative code such as ASP.NET or XAML or even HTML is still code. Lines of code is even moer useless a measurement here as it is in C, C++ or C#. Number of XML Nodes or number of XML Elements may be better counts of complexity in these declarative languages.

What I wanted to point out, is that it is now possible to use GridView talking to Postgresql with Mono without any code behind in C# or VB.NET.

Default.aspx:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>Npgsql with SqlDataSource Example Page</title>
</head>
<body>
<form id=”form1″ runat=”server”>

<asp:SqlDataSource ID=”SqlDataSource1″ runat=”server” ConnectionString=”<%$ ConnectionStrings:NpgsqlConnectionString %>” ProviderName=”<%$ ConnectionStrings:NpgsqlConnectionString.ProviderName %>”
SelectCommand=’select firstname,lastname,age from people’></asp:SqlDataSource>

<asp:GridView ID=”GridView1″ runat=”server” DataSourceID=”SqlDataSource1″Â >
</asp:GridView>

</form>
</body>
</html>

Web.config:

<?xml version=”1.0″?>
<configuration>
<connectionStrings>
<add name=”NpgsqlConnectionString” connectionString=”server=localhost;user id=test;password=test;database=test” providerName=”Npgsql” />
</connectionStrings>
<system.data>
<DbProviderFactories>
<add name=”Npgsql Data Provider” invariant=”Npgsql” support=”FF” description=”.Net Framework Data Provider for Postgresql Server” type=”Npgsql.NpgsqlFactory, Npgsql, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7″ />
</DbProviderFactories>
</system.data>
</configuration>

Of course this assumes you have a Postgresql database named test with a table named people with columns firstname, lastname, age.

Bugzilla sucks less, Mono still rocks

A couple of years ago I filed a Mono bug and it was fixed the next day.

I had the same experience a last week.

I filed the bug on April 29th at 23:18 and by April 30th at 7:07 am the bug was fixed in SVN and the case closed! I even filed the bug under the wrong topic and didn’t have very good helpful information in my bug report.

The patch solved the problem and now you can use SqlDataProvider with something other than SqlClient data source. Tests with Npgsql work great. My bugzilla experience this time around was smoother than I remember from two years ago.

Thanks mono team. 8hr turn around time is AMAZING!