Scott Hanselman

More dasBlog 1.7 changes coming soon

January 1, '05 Comments [3] Posted in ASP.NET | DasBlog | HttpModule | Bugs | Tools
Sponsored By

Omar and I are still busting our butts on a "newtelligence dasBlog Community Edition 1.7" release in the next few weeks. There will likely be a number of changes, many of which Omar has on the dasBlog Wiki.

In the last week we've:

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Testing Code-Generated Code with NUnit, Temporary Files, Voodoo, Rubber Bands and Reflection

January 1, '05 Comments [1] Posted in ASP.NET | NUnit | XML
Sponsored By

Generatedunittestprocess2Here's a little technical content for y'all. I write this on my new iJoy as the wife watches Lifetime this New Year's Day.

We're into Unit Testing here and getting more so every day. We also do a lot of code generation as well, and struggled with how to test that the code generation works from end to end.

We annotate XSDs to describe our objects. We have an XSD "DOM" Adapter that makes XML Schema documents look more friendly to consumers. We then use CodeSmith to spin through the "DOM" and generate code. Then we need to compile the generated code and hope it's correct. It's kind of a drawn out process.

However, since these objects are so fundamental to everything else that we do, it's important to test their generation. These objects should compile, have the correct attributes, be create-able at runtime, and serialize correctly.

Here's how we run CodeSmith in the NUnit tests to generate into temporary .g.cs files. The ".g.cs" extension is our own invention, allowing us to keep track of what's generated and what's written by hand.

We store the XML Schemas that will be generated as embedded resources in the test assemblies. That makes the Unit tests self-contained. This embedding technique was described in an earlier post. We unfold the schemas into the temporary directory and create a Corillian CodeSmith CodeRunner. The CodeRunner is a wrapper that we've written around CodeSmith to allow us to more easily run CodeSmith templates and avoid shelling out to EXEs. All this is done in [TextFixtureSetup] and deleted in [TestFixtureTearDown].

[Test()]
public void WriteTestMessagesFile()
{
CodeSmithRunner.Runner runner =
new Corillian.CodeGeneration.CodeSmithRunner.Runner();
runner.LoadTemplate(templatePath);
GenerateSource(runner,outFileMessagesNamePath,schemaMessagesPath);
}

private void GenerateSource(CodeSmithRunner.Runner runner,
string outputPath, string schemaPathIn)
{
using(StreamWriter output = File.CreateText(outputPath))
{
//deal with the schema file
Corillian.CodeGeneration.XmlSchemaExplorer.Schema schema =
Corillian.CodeGeneration.XmlSchemaExplorer.Schema.Read(schemaPathIn);
if(schema == null)
throw new ApplicationException("Schema couldn't be loaded");
Corillian.CodeGeneration.XmlSchemaExplorer.SchemaType[] types = schema.Parse();
if(types == null || types.Length == 0)
throw new ApplicationException("No types loaded from schema");
Corillian.CodeGeneration.XmlSchemaExplorer.TypeCollection typeCol =
new Corillian.CodeGeneration.XmlSchemaExplorer.TypeCollection(types,schemaPathIn);
runner.SetProperty("SchemaTypeCollection",typeCol);
runner.SetProperty("TargetNamespace","Test.Types");
runner.GenerateOutput(output);
}
}

The test above loads the CodeSmith .CST template from templatePath and outputs the resulting C# into outFileMessagesNamePath from the XSD in schemaMessagesPath.

Now that we've got generated C# in a temporary file, and assuming (since no exceptions stopped the tests) it worked, we'll want to compile the generated code into an assembly.

private Assembly Compile(string scope, string[] outputPaths)
{
Assembly retVal = compiledAsssemblies[outputPaths[0]+scope] as Assembly;
if (retVal == null)
{
Microsoft.CSharp.CSharpCodeProvider prov =
new Microsoft.CSharp.CSharpCodeProvider();
ICodeCompiler comp = prov.CreateCompiler();
string[] asms = new string[]{"System.Xml.dll",
"System.Web.dll",
"Corillian.Voyager.Common.dll",
"Corillian.Voyager.ExecutionServices.Client.dll",
"Corillian.CodeGeneration.Templates.Test.dll"};
string assemblyFileName =
Path.GetFileNameWithoutExtension(outputPaths[0]) + "." + scope + ".dll";
CompilerParameters options = new CompilerParameters(asms,assemblyFileName,true);
options.GenerateInMemory = false;
CompilerResults res = comp.CompileAssemblyFromFileBatch(options,outputPaths);
if(res.Errors.HasErrors)
{
Assert.Fail(res.Errors[0].ToString());
}

retVal = res.CompiledAssembly;
compiledAsssemblies.Add(outputPaths[0]+scope,retVal);
}
Assert.IsNotNull(retVal);
return retVal;
}

This Compile method takes an array of files to compile and returns the compiled System.Reflection.Assembly. We use the CSharpCodeProvider to compile the code. This is much cleaner and makes better use of what's available to us than doing something so coarse as shelling out to run csc.exe and loading the assembly. It also allows us to better detect compile errors. Notice the Assert.File if the CompilerResults has errors. We also keep the assembly stored away in a hashtable just in case another test calls Compile with the same main generated file.

Now that we can generate code and compile generated code into an Assembly, we need to actually create/instantiate the newly generated object and confirm that it has the characteristics we expect.

[Test()]
public void CheckDerivationAcrossNamespaces()
{
Assembly assembly = Compile("UI",
new string[]{outFileMessagesNamePath,outFileUIOnlyPath,assemblyInfo});
Type testResponse = assembly.GetType("Test.Types.SomeTestResponseMessage",true,true);
object theTestMessage =
testResponse.InvokeMember("cctor",BindingFlags.CreateInstance,null,null,null);
Assert.IsNotNull(theTestMessage);
PropertyInfo[] props = testResponse.GetProperties();
bool SomeDerivedUser = false;
bool FooTypedUser = false;
foreach(PropertyInfo prop in props)
{
if (prop.PropertyType.Name == "SomeDerivedUser" && prop.Name == "SomeDerivedUser")
{
Assert.AreEqual("SomeBaseUser",prop.PropertyType.BaseType.Name);
object[] attrs = prop.GetCustomAttributes(typeof(TagRemapAttribute),false);
Assert.IsTrue(attrs.Length == 2);
SomeDerivedUser = true;
}
if (prop.PropertyType.Name == "SomeDerivedComplexUser" && prop.Name == "FooTypedUser")
{
Assert.AreEqual("SomeBaseUser",prop.PropertyType.BaseType.Name);
object[] attrs = prop.GetCustomAttributes(typeof(TagRemapAttribute),false);
Assert.IsTrue(attrs.Length == 2);
FooTypedUser = true;
}
}
Assert.IsTrue(SomeDerivedUser ,"Didn't find a ID object of type
SomeDerivedUser in the UI's SomeTestResponseMessage!");
Assert.IsTrue(FooTypedUser,"Didn't find a ID object of type
SomeDerivedComplexUser in the UI's SomeTestResponseMessage!");

}

Here we compile an assembly from generated code and call assembly.GetType() to get the particular Type we're interested in. Now it gets interesting. We call the constructor of our type with Type.InvokeMember("cctor") and get the instance object back.

CodegenerationtestoutputIt's important to note that we have NOW compile-time references to any of these objects. They never existed at the time we wrote the tests, so there's no casting or type coercion that can be done. Everything is dynamic, but the tests are still confirming that the expect steps occured successfully. The tests are aiming to test the lifecycle of our objects, even though the objects will not be instantiated using Reflection. It's a parallel, but valid, reality.

In this year, we need to determine that our SomeTestResponseMessage contains two properties of specific types, with specific names, with specific custom attributes and we Assert each step of the way. If somehow make a subtle change that affects this use case, we'll hear about it via Test Failures.

The test results for this suite are generated by NUnit into XML then styled into HTML and combined with the full Test Suite and emailed to the team. Here's the output for just this TextFixture shown at right.

The only thing in these examples that is specific to what Corillian is our use of CodeSmith. Certainly tests could be written for other Code Generators that produce domain objects. I was particularly happy that CodeSmith provided a programmatic interface to it's stuff that allowed Patrick to create the CodeSmithRunner. That combined with the Microsoft CSharpCodeProvider makes these tests very robust (read: not fragile) and self contained. I've said it before, but I'd much rather use the correct public types than shell out whenever possible. You might remember I applied similar prejudices when calling Cassini's object model rather than running the command line.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Cannon Beach, Oregon - Panoramic Digital Photography

January 1, '05 Comments [3] Posted in Musings
Sponsored By

Mo and I went to Cannon Beach over the Christmas Holiday. I took a few pics with my Canon Exilim EX-Z3 of the Beach near Mo's Chowder. We did take some pictures of Mo at Mo's. :)

Cannonbeach2004largepanorama

This photo was stitched together with 10 pictures using the truly unparalleled Panorama Factory. I think I need to buy this software, it's amazing.

Update: Floyd/Ralf suggested I try ArcSoft's Panorama Maker as well. Wow, I'd never heard of this company, but they have a crapload of software. I did the panorama again, and it came out slightly brighter and clearer. I prefer the spartan interface of Panorama Factory, but now I'll need to do some additional tests. It appears that the advanced features and  spherical correction abilties of Panorama Factory are superior, but Panorama Maker looks to be easier for Joe-User.

Cannonbeach2004largepanorama2

Panorama Maker's simple Flash export feature is pretty amazing also...

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Happy New Year - And from My SPOT Watch as well

January 1, '05 Comments [1] Posted in Musings
Sponsored By

This was a cool surprise, my Spot Watch changed to include a dropping New Year's Eve ball to wish me a Happy New Year. That's some pretty cool attention to detail.

Happynewyearspot Happynewyearspot2

 

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Blogs and Opinions - "Viewer Mail," an icky way to end the year? Or a good way to start the New Year...

January 1, '05 Comments [6] Posted in Africa
Sponsored By

Well here's an interesting thing, considering that this is a technical blog.

Last week I wrote a post on how I was offended at CNN's posting of a picture of a white face on their home page when ~20,000 non-whites were dead (>120,000 now, likely 150,000 soon and one third were children). I felt, and still feel, that it was an ethnocentric decision by CNN.

Since, for whatever reason, CNN has posted more sensitive pictures, but not before they did two days of coverage on a Sports Illustrated Swimsuit Model who survived and a whole story on celebrities affected.  Certainly I wasn't the only one who noticed this, and a number of people mentioned it to me, both publically and privately. The Progressive Magazine did an article in the same vein as my post called "NYT says Tsunami Kills White People Too."

A U.S. government site has quote from President Bush about relief aid.

[For example], in the year 2004, our government provided $2.4 billion in food, in cash, in humanitarian relief to cover the disasters for last year. That's $2.4 billion. That's 40 percent of all the relief aid given in the world last year, was provided by the United States government. No, we're a very generous, kindhearted nation.

The interesting things are the $2.4B the government gave this year to humanitarian relief (it doesn't say if it include the Tsunami $350M), and the statement that it was 40% of all relief give in the world. It's good we gave more that any country in the world, considering that our GDP is nearly 11 MILLION MILLION dollars, almost double our nearest competitor, China, and almost greater than the entire rest of the top ten.

The government aid was originally $4M, then $35M on the third day (the same amount pledged by the Pzifer corporation alone) and today was upp'ed the amount of government-pledged aid to $350M. This number will likely change as the death toll rises. This is in comparison to the $13.6 Billion that has been pledged for Florida Hurricane relief. In another comparison, Bill Gates and his wife gave $168M last year to Malaria research alone and another $42M this year.

Anyway, I received this email today in criticism to my earlier post on CNN's ethnocentric news focus.

Shame on you. Americans pay attention to other Americans killed in disasters partly because it hits close to home, and reminds us of how those thousands of people over there feel. America is a very empathetic country.
The Americans have given $350 million dollars to this disaster. How dare anyone criticize them. As for media, anyone with an IQ over 50 knows never to trust the opinions of the media.
For some reason, America is seemingly the most criticized nation as far as it's moral standards and supposed "self-centeredness" goes. However, America gives 40% of the world's disaster relief funds every year. America rushes to help, and immediately orchestrates organizations for rescue and help whenever something goes wrong...
When 9/11 happened, who rushed to their side? Not really anyone, at least no other country in a heroic way. Instead, the Americans themselves took charge, and they didn't give anyone else any grief at all for not giving enough. America isn't perfect, but they do a lot of good for this world.
America has good intentions, and have proven time and time again their selflessness. Anyone who continues to criticize despite this has issues, and needs a reality check.
Either way, is your bitching about the wrong doings of American media helping this situation at all? No, but the American Red Cross is...
You're a flippin' hypocrite- and I'm not even American. Lay off, you come off as an arrogant swine.
[Heather Erickson-Sander]
I was bummed to get such negativity in my inbox so close to the end of the year. This email was so vituperous it triggered my spam filters, and I might not have seen it if I didn't fish it out.
 
A few things stood out in this response other than "flippin' hypocrite" and "arrogant swine" as I get those all the time. :)
 
"How dare anyone criticize [The Americans]." Personally, I think that there are few things on this earth that are beyond reasoned criticism. Certainly that's why I posted this critical email on my blog. Like it or not, American is big and worthy of both praise and criticism.
 
"When 9/11 happened, who rushed to their side?" Invoking 9/11, a tragic, but non-natural disaster that killed 1/50th of the people this tsunami did and that U.S. citizenry and government was capable of handling, doesn't seem like a reasonable parallel. Remember that over 1.5 BILLION was raised after 9/11, much of it by citizens domestically, more that could be distributed.
 
"America has good intentions, and have proven time and time again their selflessness. Anyone who continues to criticize despite this has issues, and needs a reality check." To be clear, I was criticizing CNN's editorial staff, but I can see how a media outlet can be confused as the face of a country.
 
Interestingly, she is cut-and-pasting variations of this criticism on other blogs under different names. I would encourage her to channel her enthusiasm towards more useful ends.
 
Greg Hughes and I have done what little we can by pressuring Bloggers and Google to donate their AdSense revenue. This has worked very well, and it looks like our little movement has taken off. Many other bloggers in other niches had the same idea simultaneously and we've received word that Google has noticed the movement and is exploring options.
 
I post this as the New Year fast approaches, and it's good to end the year on an introspective note. The human condition is overwhelming. Who are we to be blessed so? 150,000 people tragically dead today that weren't on Christmas, and expected to see the New Year themselves. 5 million people homeless today that weren't last week, but I sit here warm in my house. There but for the grace of God go I.
 
Acute and instant tragedies like this inspire people to give. Hearing that 150,000 died in a short period of time is overwhelming. However, as you enter the new year and plan your giving, remember that nearly 3,000,000 people die of Malaria every year, and 3,000 children every DAY. That's 250,000 people a month and causes 50% of the deaths of African children. Roughly 2% of Africans in Africa have AIDS, but 25% have Malaria each year. Give often and always. Give to those causes that you feel need help, but have a healthy perspective during this difficult time.
 
In conclusion, I'd like to point you to another useful thing.  India Today has an interesting currency neutral chart that suggests an appropriate level of giving based on your yearly and daily salary. I think it's more than reasonable to expect everyone who is able to give a few days or a week's pay to help assist in the worst natural disaster that, God willing, Insha Allah the likes of which we will never see again.
 
Give. I'll see you next year. I'll try to dial up the technical content and dial down the editiorials, thanks for your patience.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.