I’m on my new contract and building a framework for an environmental modelling algorithm originally whipped up with Excel macros. The data for the model exists in an Excel spreadsheet, and the new boss has zero interest in trucking in any form of database technology.
The framework I’m building out currently sucks the data into an ADO.NET DataSet via OLE, then does its data crunching in-memory via LINQ queries and delivers the same results that he’s getting out of VBA/Excel macros in a fraction of the time.
There’s a bunch of unit tests that puts the Excel/DataSet conversion code through its paces. When I was building it, I became dissatisfied with what I was doing with the simple Excel files that I was using with the unit tests. Hardcoding the absolute location of the files really bugged me.
It occurred to me that I might be able to pack the files into the Test assembly, and wherever the assembly was run, it could find a home (like the temporary directory of a hosting filesystem) for the files. Unsurprisingly, this kind of thing has been considered before. I ran across Patrick Caldwell’s blog post nailing how to pack files as resources into an assembly, and then retrieve that resource at runtime from within an NUnit Test. Then I found Scott Hanselman’s post which more elegantly handles stream resources.
Both approaches rely on you adding external files to your unit testing project. Their “Build Action” property is to be set to “Embedded Resource” allowing a file to be embedded within the assembly as a manifest resource. Neither solution quite does what I’m looking for, which is to have a way to do this with Assemblies in general (which neatly solves a problem that plagued me with legacy code in the previous contract). I ended up settling on a utility method that interrogates an assembly for all its resources and dumps them to a specified directory. Here it is:
Public Shared Function UnpackResources( ByRef resourceAssembly As Assembly, ByRef filePath As String) As String() Dim resourcePaths = New List(Of String) For Each resource As String In resourceAssembly.GetManifestResourceNames() Using resourceStream As Stream = resourceAssembly.GetManifestResourceStream(resource) Dim fileName As String = Path.GetFileName(resource) ' Not interested in the resource list If fileName.EndsWith("resources") Then Continue For Dim absoluteFilePath = Path.Combine(filePath, fileName) Using outputStream As New FileStream(absoluteFilePath, FileMode.Create) FileUtilityCollection.CopyStream( resourceStream, outputStream ) resourcePaths.Add(absoluteFilePath) End Using 'outputStream End Using 'resourceStream Next Return resourcePaths.ToArray() End Function
My NUnit test fixture responsible fore all Excel/DataSet conversion testing uses the above method like this:
<TestFixture()> Public Class TestExcelMediator Private AssemblyResourcePaths() As String <SetUp()> Public Sub Setup() AssemblyResourcePaths = AssemblyUtiityCollection.UnpackResources( [Assembly].GetExecutingAssembly(), FileUtilityCollection.GetTempPath() ) End Sub <TearDown()> Public Sub TearDown() For Each path as String in AssemblyResourcePaths DeleteFile(path) Next For End Sub End Class
On a final note, I discovered this morning that WordPress.com comes with code rendering support. Big hugs to the WordPress crew! You’ve made my morning! 🙂