Recently I noticed that I had a class with a constructor that had a single string parameter. For discussion lets assume that the class looked something like this.
public class SomeException : Exception { public SomeException(string message) : base(message) { } }
In my code I found several calls that looked something like:
throw new SomeException(string.Format("Could not find {0} in {1}", item, container));
This is perfectly acceptable way of creating an object but I wanted something a little cleaner. I modified the constructor’s signature to look more like the string.Format signature:
public class SomeException : Exception { public SomeException(string messageFormat, params string[] args) : base(string.Format(messageFormat, args)) { } }
This then changes the previous constructor call to:
throw new SomeException("Could not find {0} in {1}", item, container);
It may not be as obvious that the constructor is doing a string.Format on the parameters, but I don’t think it that far of a stretch for another program to see what is happening in the code.
This problem has caused me many hours of grief due to how long to just put up with it before looking for a solution. How the setting got changed is still a mystery to me.
The problem manifested itself when I set a breakpoint and proceeded to hit the Debug tool strip button in VS 2010. It is important to note that I had the setting “Require source files to exactly match the original version” (Tools»Options»Debugging»General) enabled. After my program started, the break point was disabled. The tooltip on it indicated that it was because my source file was different then my current version. Frustrated I close my program, rebuilt my project and was then able to stop at my break point and step through my code. After having to rebuild my project after every save, I eventually got frustrated enough to start searching for the solution.
Thankfully it turned out to be simple.
Tools»Options»Projects and Solutions»Build and Run
The setting for “Before building” was set to “Save all changes” and the setting for “On Run, when projects are out of date” was set to “Never build.” So every time I tried to debug it would save all of my changes, but would not build my project. Guaranteeing that any modified file would not be able to be debugged since it would always be difference then the previously built version. The simple solution was to change the value of ”On Run, when projects are out of date” to “Prompt to build” (or “Always build” if you so desire).
Here hoping this saves you some of the frustration I went through.
So tonight I had my first lesson in robotics.
My goal was to be able to open my garage door from my computer using a RS-232 (serial) relay board.
The Parts:
Assembly:
This was the easy part. Installed the driver for the USB to serial cable. Plugged in the power cable and connected it to the relay board. Connected the serial cable to the relay board and I was all set for testing.
National Control Devices provides a utility to test communication between your computer. I fired it up, selected the relay board type and COM port, and spent a few minutes giggling with glee as I watched the relay’s LEDs toggle on and off as I opened and closed the relays.
Next step was to connect the relay board to the garage door and make it open and close. For my particular Chamberlain garage door, I followed the wire from the button to where it connected to the motor unit. I attached a second wire along side this one to the motor unit, and connected the opposite end to the relay board in the normally open position.
Toggling the relay on and off now made the garage door open and close.
The code
Now all that was left was to program a simple application to send the command to the relay board to close and open the relay.
All of the commands were were nicely outlined in the manual. The commands to turn Relay One on and off are 1 and 0 respectively. In addition all commands must be proceeded with 254 to put the device in “command mode.”
Here is the code:
public static void Main(string[] args) { SerialPort port = new SerialPort("COM4"); port.Open(); port.Write(new byte[] { 254, 1 }, 0, 2); Thread.Sleep(100); port.Write(new byte[] { 254, 0 }, 0, 2); port.Close(); }
Although my garage door appeared to open and close just fine without the Thread.Sleep, I found it more appealing to actually see the LED flash on an off when my program ran, just as a visual confirmation that everything worked as expected.
Similar to my last post about using NUnit’s ValueSourceAttribute, this post offers another example of how to extend an NUnit attribute to get better unit tests.
For this example NUnit version 2.5 or greater is required.
Consider the following enum and test object.
public enum AnimalEnum : byte { None, Dog, Cat } public class ObjectToTest { public object GetValueFromEnum(AnimalEnum enumValue) { switch(enumValue) { case AnimalEnum.None: return new NullAnimal(); case AnimalEnum.Dog: return new Dog(); case AnimalEnum.Cat: return new Cat(); default: throw new InvalidOperationException(string.Format("{0} is not supported", enumValue)); } } }
We might want to write a test to ensure that all values in the enum return an object. That way, any programmer who modifies the enum will need to also modify the GetValueFromEnum method.
There are a few ways to write the test:
Both the second and third options will work, so lets try both. The second option would look something like this:
[TestFixture] public class TestFixture { [Test] public void Test_AllEnumValuesReturnAnimal() { var objectUnderTest = new ObjectToTest(); var enumAnimals = Enum.GetValues(typeof(AnimalEnum)).Cast<AnimalEnum>(); foreach(AnimalEnum enumValue in enumAnimals) { Assert.IsNotNull(objectUnderTest.GetValueFromEnum(enumValue)); } } }
A perfectly valid test that should do what we want, but I would argue there is a much cleaner way to do this.
Lets extend the NUnit ValuesAttribute.
public class AllEnumValuesAttribute : ValuesAttribute { public AllEnumValuesAttribute(Type enumType) { if (enumType.IsEnum == false) { throw new InvalidOperationException(string.Format("{0} must be an enum type", enumType.Name)); } data = Enum.GetValues(enumType).Cast<object>().ToArray(); } }
The ValuesAttribute has a protected object[] called data. NUnit uses this array when building up each test to run.
This changes our unit test to look like:
[TestFixture] public class TestFixture { [Test] public void Test_AllEnumValuesReturnAnimal([AllEnumValues(typeof(AnimalEnum))] AnimalEnum enumValue) { var objectUnderTest = new ObjectToTest(); Assert.IsNotNull(objectUnderTest.GetValueFromEnum(enumValue)); } }
IMO this is a much cleaner unit test, but there is another advantage of using the ValuesAttribute. Depending on the test runner, each enum value will appear as its own unit test (The test runner that comes with the NUnit framework will do this). So the above unit test will actually display as three unit tests, since the enum has three values.
Today I was faced with a very interesting problem. Given a user control the context menu was not being shown the first time the user right clicked. There was nothing special about the user control nor the context menu except that the menu items were dynamically generated during the context menu’s opening event.
Consider the follow code snippet:
bool _showItem1; bool _showItem2; private void ctxMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e) { _ctxMenuStrip.Items.Clear(); if (_showItem1) { _ctxMenuStrip.Items.Add("Item 1", null, item1_clickHandler); } if (_showItem2) { _ctxMenuStrip.Items.Add("Item 2", null, item2_clickHandler); } } private void item1_clickHandler(object sender, EventArgs e) { } private void item2_clickHandler(object sender, EventArgs e) { }
The above code does have the issue i described above where the context menu is not show the first time the user right clicks on the user control.
As it turns out when the context menu is building up the CancelEventArgs to pass to the Opening event, it does the following.
CancelEventArgs e = new CancelEventArgs(this.DisplayedItems.Count == 0); this.OnOpening(e);
So the first time the context menu is shown the Cancel property on the CancelEventArgs is set to true because no items have been added. While all subsequent times the context menu is properly displayed.
A more appropriate fix would be something along the lines of
private void ctxMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e) { _ctxMenuStrip.Items.Clear(); if (_showItem1) { _ctxMenuStrip.Items.Add("Item 1", null, item1_clickHandler); } if (_showItem2) { _ctxMenuStrip.Items.Add("Item 2", null, item2_clickHandler); } e.Cancel = _ctxMenuStrip.Items.Count > 0; }
References
Recently I have run into the problem where I created an enum to keep track of two states within my object. Sure could have just used a boolean but the enum seemed to make the code easier to read.
private enum SomeEnum : byte { FirstValue = 0, SecondValue = 1 } private SomeEnum _value; public void ToggleValue() { _value ^= (SomeEnum)1; //Alternatively //_value = (SomeEnum)(((int)_value + 1) % 2); }