Showing posts with label sample_code. Show all posts
Showing posts with label sample_code. Show all posts

Monday, April 19, 2010

Unit testing random methods

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/unit_testing_random_methods.htm]

You can unit test random methods by running the method in a loop and checking for statistical results.

For example, say you have a method to return a random integer between 1 and 10 (this could just as easily be to return any type between any range). You could run the test 100,000 times and confirm that the statistical distribution makes sense. With a sufficient sample size, there should be at least one of each value. The mathematically advanced could apply better statistics, like checking the proper distribution.

Here's a simple sample. It runs the random method in a loop, and checks just that each value was returned at least once.

public class MathHelper
{
    private static Random _r = new Random();

    public static int GetRandomInt()
    {
        //return Random int between 1 and 10
        //recall that upper bound is exclusive, so we use 11
        return _r.Next(1, 11);
    }
}

[TestMethod]
public void Random_1()
{
    int iMinRandomValue = 1;
    int iMaxRandomValue = 10;

    //Initialize results array
    //ignore 0 value
    int[] aint = new int[11];
    for (int i = iMinRandomValue; i <= iMaxRandomValue; i++)
    {
        aint[i] = 0;
    }

    //Run method many times, record result
    //Every time a number is returned, increment its counter
    const int iMaxLoops = 1000;
    for (int i = 0; i < iMaxLoops; i++)
    {
        int n = MathHelper.GetRandomInt();
        aint[n] = aint[n] + 1;
    }

    //assert that each value, 1-10, was returned
    for (int i = iMinRandomValue; i <= iMaxRandomValue; i++)
    {
        Assert.IsTrue(aint[i] > 0,
            string.Format("Value {0} never returned.", i));
    }

}

Of course, this assumes you're explicitly trying to test the random method - you could mock it out if the method is just a dependency and you're trying to test something else.

Monday, May 12, 2008

Converting an object from JSON and back in Silverlight

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/converting_an_object_from_json_and_back_in_silverlight.htm]

JSON (JavaScript Object Notation) provides a convenient way to serialize an object, like "Employee" with first and last name, to a string. This can be very useful in Silverlight apps, such as when you need to pass complex objects to and from a web service.

There are APIs in Silverlight that make it relatively easy to roundtrip an object from a JSON string and back. Here are two wrapper methods.

These use the assemblies System.IO and System.ServiceModel.Web (which contains the necessary namespace System.Runtime.Serialization.Json). It also uses the two static utility methods I blogged about to roundtrip from a MemoryStream and back (GetMemoryStreamFromString and GetStringFromMemoryStream).

    public static T ConvertFromJSON(string strJSON)
    {
      System.Runtime.Serialization.Json.DataContractJsonSerializer d =
          new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));

      MemoryStream m = GetMemoryStreamFromString(strJSON);
      T obj = (T)d.ReadObject(m);

      return obj;
    }

    public static string ConvertToJSON(T obj)
    {
      System.Runtime.Serialization.Json.DataContractJsonSerializer d =
          new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));

      MemoryStream m = new MemoryStream();
      d.WriteObject(m, obj);
      string strJSON = GetStringFromMemoryStream(m);

      return strJSON;
    }

I assume that the code is self-explanatory. Perhaps the only note is that it uses Generics to dynamically set the return type. You could also optimize the methods for performance by instantiating the DataContractJsonSerializer once, and making these utility methods, as opposed to static methods that re-create it every time.

Monday, April 21, 2008

JavaScript enums

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/javascript_enums.htm]

While JavaScript does not explicitly have the enum keyword, you can work around it using JS rich objects to get the functional equivalent. Here's a minimalist example that defines the enum, passes it in as a parameter, and then checks for it in a switch-case statement. Although, this doesn't throw a "compile time" exception if you pass in an invalid value.

    var Enum_Colors =
    {
      Red:0,
      Blue:1,
      Green:2,
      Yellow:3
    };

   
    function DoStuff()
    {
      TestEnum(Enum_Colors.Green);
    }

    function DoError()
    {
      TestEnum(Enum_Colors.Unknown); //Bad
    }
    function TestEnum(objColorEnum)
    {
      var str;
      switch(objColorEnum)
      {
        case Enum_Colors.Red:
          str = "red";
          break;
        case Enum_Colors.Blue:
          str = "blue";
          break;
        case Enum_Colors.Green:
          str = "green";
          break;
        case Enum_Colors.Yellow:
          str = "yellow";
          break;
        default:
          str = "none";
          break;
      }
     
      alert("The enum passed in is: " + str);
    }

 Thanks to VS2008, you at least get JS intellisence on the "Enum_Colors" object, so that's better than just typing in error-prone literal strings.

Sunday, April 20, 2008

Convert from a MemoryStream to a string and back

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/convert_from_a_memorystream_to_a_string_and_back.htm]

A stream in .Net is a sequence of bytes. There are several types of streams. A common one is the MemoryStream which uses memory for its storage (as opposed to a file system, or something else). Several readers and writers require a stream as an input parameter, and you'll find that sometimes you'll just want to be able to easily convert from a string to a MemoryStream and back. Here are two easy utility methods to do that:

    public static string GetStringFromMemoryStream(MemoryStream m)
    {
      if (m == null || m.Length == 0)
        return null;

      m.Flush();
      m.Position = 0;
      StreamReader sr = new StreamReader(m);
      string s = sr.ReadToEnd();

      return s;
    }

    public static MemoryStream GetMemoryStreamFromString(string s)
    {
      if (s == null || s.Length == 0)
        return null;

      MemoryStream m = new MemoryStream();
      StreamWriter sw = new StreamWriter(m);
      sw.Write(s);
      sw.Flush();

      return m;
    }

 

We can easily test these with a round-trip method. Note that ideally we'd have one test for each specific method, but this is just for demo purposes:

 

    [TestMethod]
    public void Convert_RoundTrip()
    {
      string s1 = "Hello World!";
      MemoryStream m = GetMemoryStreamFromString(s1);

      Assert.AreEqual(12, m.Length);

      string s2 = GetStringFromMemoryStream(m);

      Assert.AreEqual(s1, s2);
    }

 

 

Sunday, October 21, 2007

Silverlight: Read xml file in FireFox (solve "Data at the root level is invalid")

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/silverlight_read_xml_file_in_firefox_solve_data_at_the_ro.htm]

Any app eventually needs to read data; and it's very likely that for Silverlight, that data will be XML files on your web server. For example, in the real-time strategy TruckWars game, each level is stored as an XML file (named 1.xml, 2.xml, etc...). The Silverlightquickstart tutorials describe how to load an Xml file into an XmlReader (there is no XmLDocument for silverlight yet). While this works great in IE, it actually has a problem in FireFox. FF tries to read the xml file, but it starts with three extra bits used for reading the encoding type. These three extra bits screw up the XmlReader, and you get the error:

 

"Data at the root level is invalid. Line 1, position 1."

 

This has something to do with theunicode.GetPreamble().

 

Practically, there's probably some way to overload the reader class, or set something on the Xml file. But I couldn't figure that out. I tried several things:

  1. Use reader.ReadToFollowing("myNode"); But those first few bytes prevent me from reading anything.

  2. I tried removing , but no luck

  3. Based on anMSDN forum, I tried removing this first line:

  4. In the StreamReader class, I set the detectEncodingFromByteOrderMarks constructor property (trying both true and false), but no luck.

  5. I tried modifying the Xml Reader to directly get from URI. However, I got the error: "Support for http:// URIs is not yet implemented."

  6. I tried overloading the XmlReader with XmlReaderSettings (and setting IgnoreProcessingInstructions )

  7. I tried reading the first three bytes of stream to "skim off" the problem characters, but it still had the same problem

So, none of those attempts worked. Eventually, I got a work-around. I would read the entire xml file into a string, and then skip the first problem characters until I go to the "

    public static XmlReader CreateXmlReader(string strRelativePath)    {      HttpWebResponse response = null;      StreamReader sr = null;      try      {        //first create standard stream:        Uri u = new Uri(strRelativePath, UriKind.Relative);        HttpWebRequest request = new BrowserHttpWebRequest(u);        response = request.GetResponse();        Stream content = response.GetResponseStream();        sr = new StreamReader(content);        string s2 = sr.ReadToEnd();        //Skim off unicode.GetPreamble()        //In firefox, this would be first three bytes for UTF8        int intIndex = s2.IndexOf(");        s2 = s2.Substring(intIndex);        StringReader sr2 = new StringReader(s2);        return XmlReader.Create(sr2);      }      catch (Exception ex)      {        throw;  //Wrap in try catch for now. Will add better error-handling later.      }    }

This solved my problem, worked in both FireFox and IE, an performed well enough for my needs.

Sunday, August 19, 2007

Converting a List to an Array and back using Generics

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/converting_a_list_to_an_array_and_back_using_generics.htm]

UPDATE (8/21/2007): A comment from Martin shows that you can actually do this much simpler, using standard .Net constructors and methods. So, this code snippet is now just an example showing some features of Generics.

 

I love Generics in C# 2.0 because they let you abstract out type, which lets you code at a greater level of reusability. For example, you could use Generics to abstract out return type. You could also use Generics for standard set and conversion operations.

 

Say your code juggles between System.Collections.Generic.List and arrays. Lists are great for adding and removing items; arrays are just ubiquitous. You could easily write a converter utility methods to handle this:

 

    public static List ConvertArrayToList(T[] myArray)
    {
      if (myArray == null)
        return null;

      List myList = new List();

      for (int i = 0; i < myArray.Length; i++)
      {
        myList.Add(myArray[i]);
      }
      return myList;
    }

    public static T[] ConvertListToArray(List myList)
    {
      if (myList == null)
        return null;

      T[] myArray = new T[myList.Count];

      for (int i = 0; i < myArray.Length; i++)
      {
        myArray[i] = myList[i];
      }
      return myArray;
    }

 

Here we use the generic 'T' to abstract out an input value, the return type, and even to create a new object within the method. It's obviously much better than writing custom converter methods for all your object collections, or every using the ArrayList and unboxing.

 

Here's a simple unit test that shows how to call each method. It round-trips between the two - i.e. you should be able to convert from a list to an array and back to a list, and the final list should match the original one.

 

    [TestMethod]
    public void Convert_ListToArrayRoundTrip_1()
    {
      string[] astr = new string[] { "a", "bb", "ccc" };
      List<string> lstr = MyClass.ConvertArrayToList<string>(astr);

      string[] astr2 = MyClass.ConvertListToArray<string>(lstr);

      Assert.AreEqual(astr.Length, astr2.Length);
      Assert.AreEqual(astr[0], astr[0]);
    }

 

Besides convert methods, you could also write simple set methods, like something to remove all the items from a list:

 

    public static List RemoveItems(List mainList, List itemsToRemove)
    {
      if (mainList == null)
        return null;

      if (itemsToRemove == null || itemsToRemove.Count == 0)
        return mainList;

      for (int i = 0; i < itemsToRemove.Count; i++)
      {
        mainList.Remove(itemsToRemove[i]);
      }
      return mainList;
    }

 

You could write a test for the basic case:

 

    [TestMethod]
    public void RemoveItems_Some()
    {
      List<int> iMain = new List<int>();
      iMain.AddRange(new int[] { 10, 20, 30, 40, 50 });

      List<int> iRemove = new List<int>();
      iRemove.AddRange(new int[] { 30, 50, 70 });

      List<int> iFinal = MyClass.RemoveItems<int>(iMain, iRemove);

      Assert.AreEqual(3, iMain.Count);
      Assert.AreEqual(10, iMain[0]);
      Assert.AreEqual(20, iMain[1]);
      Assert.AreEqual(40, iMain[2]);
    }

 

Disclaimer: obviously you could have a lot more unit tests to fully test these methods.

 


Living in Chicago and interested in working for a great company? Check out the careers at Paylocity.

 

Wednesday, June 6, 2007

Using Generics for dynamic return type and validation.

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/using_generics_for_dynamic_return_type_and_validation.htm]

Generics are a .Net 2.0 feature that essentially let you abstract out type. You can learn a lot about generics on MSDN.

One problem that generics can solve is how to have a method dynamically return a given type. For example, in the snippet below, the method GetData returns different types depending on what you pass in - either a double or an Int32. This is useful for creating a generalized method to parse out (and potentially validate) data. Note that the consumer of the GetData method need not deal with conversion - it receives a strongly typed value.

While this is just a trivial snippet, it's a nice demo of one of the features of generics.

    [TestMethod]
    public void DemoGenerics()
    {
      int i = GetData("123");
      double d = GetData("456");

      Assert.AreEqual(Convert.ToInt32(123), i);
      Assert.AreEqual(Convert.ToDouble(456), d);

    }

    public static T GetData(string strData)
    {
      string strType = typeof(T).Name;

      switch (strType)
      {
        case "Int32":
          return (T)(object)Convert.ToInt32(strData);
        case "Double":
          return (T)(object)Convert.ToDouble(strData);
        default:
          throw new Exception("Type not supported");
      }
    }

 


Living in Chicago and interested in a great company? Check out the careers at Paylocity.

Sunday, November 19, 2006

Adding an Event to a User Control (Code Sample)

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/adding_an_event_to_a_user_control.htm]

I had talked about how to trigger an event from a UserControl.

This ability has many benefits, such as with refactoring. For example, suppose a UserControl is hosted on many different pages, and each page requires that the control have slightly different validation that incorporates values from the host page. One way to do this is to have the UserControl call a validation method on the host page.

Here's a code snippet you can download that shows how to have a UC call a method on its parent. The idea is to add an event member to the control, and hook it up with a delegate. (I had initially seen this technique from an article on MSDN several years ago).

This specific example has four files:

  • A UserControl - RecordNav.ascx and RecordNav.ascx.cs
  • A host page - HostRecordNav.aspx and HostRecordNav.aspx.cs

The UserControl contains an event "UpdateDate" and the host page adds a method to handle the event: RecordNav1_UpdateData.

    RecordNav1.UpdateData += new AspxDemo_Events_RecorNav.UpdateDataEventHandler(RecordNav1_UpdateData);