Thursday, October 25, 2012

C#: Testing for CLS Compliance

I was working on refactoring some C# code in an assembly when some of the error messages about CLS Compliance didn't seem to make sense.  It was then I discovered that the assembly had not been marked as CLS Compliant.  I plan on writing a second post on some of the reasons for CLS Compliance and also some tips on interpreting compiler warning messages.  But in this post I just want to show a simple unit test that will verify that an assembly has been marked as compliant.

First to visually check if an assembly is compliant, look for this attribute declaration in the assembly.cs source code file:

[assembly: CLSCompliant(true)]

The unit test to check for this is quite simple and just loads the assembly's meta-data.  I am using NUnit but this code can be used with any testing framework.

Here's the test fixture class, with some comments following:

    [TestFixture]
    [CLSCompliant(false)]
    public class AssemblyTestFixture
    {
        Assembly thisAssembly;
        object[] attributes;

        [SetUp]
        public void Setup()
        {
            thisAssembly = Assembly.GetExecutingAssembly();
        }

        [Test]
        public void IsCLSCompliant()
        {
            attributes = this.thisAssembly.GetCustomAttributes(typeof(CLSCompliantAttribute), false);
            Assert.AreEqual(attributes.Length, 1);
            CLSCompliantAttribute csl = (CLSCompliantAttribute)attributes[0];
            Assert.IsTrue(csl.IsCompliant);
        }
    }


Some notes on this code:

1. I mark test fixtures as not CLS Compliant because this is not production code and I often do strange things in Unit Tests. The compiler warnings are disabled this way.

2. Make sure this code is in the assembly you want to test. GetExecutingAssembly always refer to the assembly running the code.

3. If you want to test some other assembly, load the metadata using one of the other Assembly class methods such as Load, LoadFile or LoadFrom.



Thursday, June 24, 2010

SQL: Case, Switch and Data Models

I was trying to remember how to do a case statement in an MS-Access Query. Having worked mostly in SQL Server the last while I forgot that MS-Access uses the switch keyword instead of case. The syntax is very similar.

A case or switch statement in SQL allows you to translate a specific value of a field into another value. It is often used to translate something meaningless like an enum or numeric identifier into something readable. It is often used in views or reports.

In the following example the MSAccess switch statement is used to translate an enumeration field into readable text:

 SELECT switch([T_Member.FamilyTypeId]=1,"parent",[T_Member.FamilyTypeId]=2,"dependent") AS SomeFieldName FROM SomeTable


SQL Server Books Online (2005) shows a simple example of the case statement:

USE AdventureWorks2008R2;
GO
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO




Now that I've shown you how to do these statements properly, I'm going to argue why you should never use them.

Almost always a case statement means the data model is incomplete. A case statement basically inserts ad hoc lookup tables randomly though-out your SQL statements. As good designers will say, hard-coded text values or numeric literals in any type of code are a maintenance nightmare. How hard is it to extend the data model to provide text definitions of the things you are translating with a case statement?

I feel the same way about the use of case statements in programming languages. The logic is static and cannot be changed except through rebuilding and redeploying. Adding an additional case label to a statement is out of reach for the system administrator, whether SQL or code.

Case or switch fields are not editable by the user. In some cases views that use them can make the entire row not editable. But almost all GUIs support editing of foreign keys through drop downs boxes.

I would argue that case and switch statements should never be used in SQL statements, and focus instead on complete data models, with proper relationships.

Tuesday, January 12, 2010

Testing C# Class Properties With NUnit - Part 2

In a previous post I showed how to auto-test object properties in a NUnit test. I forgot to include a function called GetProperties() which was referenced in the code example. Here it is:


       /// <summary>
        /// An test that iterates through an object's properties and does
        /// a very minimal test on get/set integrity.
        /// </summary>
        /// <param name="patient"></param>
        /// <returns></returns>
        public ArrayList GetProperties(Patient patient)
        {
            ArrayList Properties = new ArrayList();
            PropertyInfo[] propertyInfo = patient.GetType().GetProperties();

            foreach(PropertyInfo item in propertyInfo)
            {
                Properties.Add(item.Name);
            }

            return Properties;
        }

Of course this is pretty simple minded and should be re-factored in any number of ways. Most importantly to get rid of the specific object reference and make it generic. Cut and paste programming makes us angry, very very angry.

Friday, May 22, 2009

The Weird Syntax of SQL DELETE From a JOIN

It is perfectly legal in most SQL dialects to DELETE records that come from a JOIN clause. However, I never remember the syntax because its kind of strange and I don't do it often.

I wrote the following example in SQL Server 2005:

delete from arledger 
from arledger
inner join arinvoice on arinvoice.arinvoiceid = arledger.invoicenumber
where arinvoice.brokersaleid = 2259




Nothing complicated. Just note line 2 where the FROM clause is repeated.

Thursday, March 5, 2009

Current Reading

I'm currently reading Pro WPF in C# 2008 by Matthew MacDonald. So far it seems well written and I'm getting a good feel for WPF. I'm anxious to do my first WPF project but didn't want to just jump in without some background.

However, ultimately you can't learn a technology without jumping in and making a whole bunch of stupid mistakes.


Wednesday, March 4, 2009

Article on Setting Properties Dynamically

For the previous post on NUnit and testing properties using reflection I was indebted to this article. The code examples in this article are in VB.Net.

Testing C# Class Properties With NUnit

In their book Pragmatic Programing Andrew Hunt and David Thomas argue that all programmers should adhere to the DRY principle. DRY stands for do not repeat yourself. Its a daily battle to keep my code library from descending into the usual cut and paste mess of massively duplicated code.

I had a few C# classes that had an high number of properties and I wanted to make sure each property had a unit test to make sure they were assigning correctly. I envisioned this as being massively tedious. I thought that a better approach might be to iterate through the properties using reflection and test them by setting and retrieving test values. This would also mean I wouldn't have to change the unit test if I added, deleted or renamed properties.

The code I came up with is very sketchy and preliminary but it does work. It can be refactored any number of ways to suit invididual tastes. In this unit test the class Patient is being tested.

I'm only testing properties of type String and Integer in this example. You can add any type you want. I am thinking about a way to test these properties that is type independent.

        [Test]
public void Properties()
{
Patient patient = new Patient();
int intTestData = 0;

foreach (string propertyName in GetProperties(new Patient()))
{
Type patientType = patient.GetType();
PropertyInfo property = patientType.GetProperty(propertyName);


string stringTestData;

if (property.PropertyType == typeof(System.String))
{
intTestData++;
stringTestData = String.Format("Testdata{0}", intTestData);

Console.WriteLine(String.Format("Testing property {0} of type {1} with value {2}", propertyName, property.PropertyType.ToString(),stringTestData));

if (property.CanWrite == true && property.CanRead == true)
{
property.SetValue(patient, stringTestData, null);
Assert.AreEqual(stringTestData,property.GetValue(patient,null));
}
}

if (property.PropertyType == typeof(System.Int32))
{
property.SetValue(patient, intTestData, null);
Assert.AreEqual(intTestData, property.GetValue(patient, null));
}
}
}