Dan Maharry

Are bug fix tests unit or integration?

by

Jeremy Miller asked how do you know if your TDD approach is working earlier today. And then I wrote the following test which covers a particular bug \ feature of xsd.exe I found a while ago. It's incomplete, but then I started worrying, is this approach right? I'm testing one method which takes a schema and returns a CodeNamespace which has been altered. I need to make sure the result addresses the bug that was discovered which this test seems to do. But is it a unit test? Shouldn't it have fewer asserts as I've read in the past? Shouldn't I be satisfied with the tests I've also written on routines that perform the tweaking on the CodeNamespace once it has been generated, but which do not make sure that all those smaller routines work together to produce the overall result? What are your thoughts out there.

[Test]
public void Convert_ComplexTypeHasElementInChoiceWithNoType
_GeneratedCodeFixesTypeOfObjectBug()
{
XmlSchema schema = sb.CreateSchemaContaining(new XmlSchemaObject[] {
sb.RootElementWithSeparateType(rootElementName, rootTypeName),
sb.NamedComplexTypeContaining(rootTypeName, 
sb.ChoiceOf(sb.DateStringAndEmptyElements(
dateElementName, stringElementName, emptyElementName)))
});//Convert it
CodeNamespace ns = sc.ConvertSchemaToCodeNamespace(schema);//Check that the empty class has been generated
CodeDomAssert.AssertClassExists(ns, emptyElementName + "Class");//Find the original class and check it has a choice element in it //which isn't typeof(object) but which is typeof(emptyElementClass)foreach (CodeTypeDeclaration typeDec in ns.Types)
{
if (typeDec.Name == rootTypeName)
{
//Check that the choice element is fielded by a property of type 
//system object tagged with
//[XmlElement("emptyElement", typeof(emptyElementClass))]
//Create attributes to check
CustomAttribute emptyElementAttribute = new CustomAttribute(
CustomAttributeType.Simple, elementAttributeName,
new AttributeArgument[] {
new AttributeArgument(
CustomArgumentType.Simple, String.Empty, emptyElementName),
new AttributeArgument(
CustomArgumentType.TypeOf, String.Empty,  
emptyElementName + "Class")
});
CodeDomAssert.AssertFieldExists(
typeDec.Members, MemberAttributes.Private, "System.Object",
HelperFunctions.DefaultXsdGeneratedFieldName(defaultGeneratedPropertyName));
CodeDomAssert.AssertTaggedPropertyExists(
typeDec.Members, defaultGeneratedPropertyName, "System.Object",
true, true, 
HelperFunctions.DefaultXsdGeneratedFieldName(defaultGeneratedPropertyName),
new CustomAttribute[] { emptyElementAttribute });
}
}
}

IDisposable - Why and When

by

I like using the C# using keyword. It's great in dealing with connections and transactions, disposing of resources as we go, keeping an app lean and mean, so to speak. So maybe it's not surprising that I figured out maybe I should do the same in my little app. So here's the suggestion.

static void Main(string[] args)
{
XmlSchema schema;
CodeNamespace codeNamespace;//Load schema into memoryusing (SchemaLoader loader = new SchemaLoader())
{
schema = loader.LoadSchemaFromFile(args[0]);  
}
//Convert schema into namespaceusing (SchemaToNamespaceConverter converter 
= new SchemaToNamespaceConverter())
{
codeNamespace = 
converter.ConvertSchemaToCodeNamespace(schema);
}
//Manipulate namespaceusing (CodeNamespaceTweaker tweaker = new CodeNamespaceTweaker())
{
tweaker.ChangeAllFieldPropertyNameCombosInNamespace(codeNamespace);
}
//Write the new code to a fileusing (NamespaceToFileWriter writer = new NamespaceToFileWriter())
{
writer.WriteNamespaceToFile(codeNamespace, args[1]);
}
}

And from this, several questions issue:

  1. This is overkill right?
  2. So when should a class really inherit from IDisposable so you can use it in a using statement? Microsoft's guidelines for implementing it infer that you only need to do so if the class uses a Handle to point in memory, or uses an object which you'll want disposed before the garbage collector would do it normally anyway. ergo not for convenience. But really, when do you actually implement it? Answers in comments please?
  3. If I leave my code as it is above, do each of the classes in the using statements actually get finalized \ garbage collected faster than if I wrote something like the following?
static void Main(string[] args)
{
XmlSchema schema;
CodeNamespace codeNamespace;//Load schema into memory
SchemaLoader loader = new SchemaLoader();
schema = loader.LoadSchemaFromFile(args[0]);//Convert schema into namespace
SchemaToNamespaceConverter converter = new SchemaToNamespaceConverter();
codeNamespace = 
converter.ConvertSchemaToCodeNamespace(schema);//Manipulate namespace
CodeNamespaceTweaker tweaker = new CodeNamespaceTweaker();
tweaker.ChangeAllFieldPropertyNameCombosInNamespace(codeNamespace);//Write the new code to a file
NamespaceToFileWriter writer = new NamespaceToFileWriter();
writer.WriteNamespaceToFile(codeNamespace, args[1]);
}

Answers anyone?

[Updated 13/11/2006]

Philip Rieck and a few others answered this question for me on the C# forum along with a few links for more information on IDisposable. Great thanks to them. For quick reference, the answers are.

  1. Yes it is.
  2. Implement IDisposable when you want a resource freed quickly rather than an object. Calling Dispose won't free an object any faster than not implementing IDisposable and waiting for the garbage collector to show up.
  3. No. The Garbage collector will take as long as it usually takes to collect an object whether you call finalize or not.

Do look at the more comprehensive answers in the post on the C# forums. You learn something every day.

XmlSchemas vs XmlSchemaSet

by

Strangeness. Carrying on at a leisurely pace with my XSD-entender TDD project, I come across a couple of issues. The first is yet another inconsistency inside the XmlSerializer although not a bug. It’s a case of obsolescence. In .NET 1.0, you compile an XmlSchema object like this.

XmlSchema xsd = new XmlSchema();
xsd.Compile();

Now in .NET 2.0, Microsoft marked the XmlSchema.Compile() method as Obsolete in favour of using the XmlSchemaSet.Compile() method like so

XmlSchema xsd = new XmlSchema();
XmlSchemaSet set = new XmlSchemaSet();
set.Add(xsd);
set.Compile();

We can add more schemas into the schemaset and then compile them into one large schema which we can access through such properties as GlobalItems and GlobalTypes. We can also continue to access the individual schemas through the Schemas property. Good so far, but here’s the problem.

As part of emulating how xsd.exe works, we use an XmlSchemaImporter object like so

//Create importer for the schema
XmlSchemaImporter importer = new XmlSchemaImporter(schemas);// Iterate through top-level (global, not local) elements in the schemas // and export code for each into the namespaceforeach (XmlSchema schema in schemas)
{
foreach (XmlSchemaElement element in schema.Elements.Values)
{
// Import the mapping from XML to .NET code and export it to the code namespace
XmlTypeMapping mapping = importer.ImportTypeMapping(element.QualifiedName);
exporter.ExportTypeMapping(mapping);
}
}
return ns;

The XmlSchemaImporter object only takes an XmlSchemas object in its constructor. So, having compiled a schema in a SchemaSet, I then need to take it out of there and put it in the XmlSchemas collection instead with something kludgey(?) like this

public XmlSchemas MoveSchemaSetToXmlSchemas(XmlSchemaSet set)
{
XmlSchemas schemas = new XmlSchemas();
XmlSchema[] schemaArray = new XmlSchema[set.Count];
set.CopyTo(schemaArray, 0);foreach (XmlSchema xsd in schemaArray)
{
schemas.Add(xsd);
}
return schemas;
}

Now the XmlSchemas object also has a Compile() method but calling it seems to do nothing. The IsCompiled property of the object will remain false even if the object contains a valid schema. Even MSDN says it is for calling internally only. Fair enough. So how do you compile several schemas into one and then pass them into a XmlSchemaImporter object?

  • The obvious way would be to create a new XmlSchemaImporter constructor which takes a XmlSchemaSet object. Well yes, but MS has already been asked that and they’ve said no. Not even for .NET 3.5 by the looks of it.
  • Well then, how about being able to export the compiled schema from a schemaset into a single XmlSchema and thence into a XmlSchemas? No word yet but something like XmlSchema xsd = schemaset.ExportCompiledSchema() would be nice.

In the end, the app works with the kludge but is it really necessary? Let’s see if option two ever shows up.

TDD, XSD and CodeGen, Part 3: Changing Field and Property Names

by

Download all the test and program code generated by the end of this article here.

With a selection of schemas tested and a set of CodeDom tests established for the checks we're most likely to need in part 2, let's turn our attention to the tweaks we want to make to the generated CodeNamespace members. Here's my initial list - we could well add to it later on providing more tests are written to cover the additional code.

  1. Change the field \ property names from elementField\Element to element\Element
  2. Change the type of a field \ property
  3. Change the name of a type 
  4. Change the way dates are serialized.
  5. Change the way boolean values are serialized.

In this post, we'll build the code that makes the first these changes.

More...

TDD, XSD and CodeGen : Part 2, Converting Complex Types and Attributes

by

Download code covering all the tests and code so far from this series here.

In the last episode, we started building our alternate to xsd.exe and wrote a set of five tests that made sure the converter worked against the smallest possible schema. We also learnt about building basic schemas programmatically. Next up, we'll look at some more basic pieces of a schema and start working in the CodeNamespace area.

More...