Archive for the ‘C#’ Category.

Log4Net configuration and scope extension

I had the need to setup Log4Net logging in a new project the other day. It is fairly easy to setup, just add the listeners you want in the configuration files. Then use it, of course you get most things for free the log level etc. We also wanted to make it super easy to use Scope, so I added a LogExtension that takes care of that. The idea is if you forget to close the scope it will be automatically done once the scope object gets garbage collected. Below is example code including UnitTests.

logger_sample

Chocolatey

I played with Chocolatey today, I figured lets create an package to setup a development machine. Add handy packages that you might want starting out on a new machine. This is handy as well when you have a new developer joining your team, you can set them up with some common tools.

First create the spec file as below

<?xml version=“1.0”?>
<package>
  <metadata>
    <id>SoftwareCreations.devset</id>
    <title>SoftwareCreations.devset</title>
    <version>0.09</version>
    <authors>Orn Kristjansson</authors>
    <summary>Software Creations, installs dev tools.</summary>
    <owners>Orn Kristjansson</owners>
    <description>Installs handy development tools.</description>
    <projectUrl>https://github.com/ornatwork/</projectUrl>
    <tags>SoftwareCreations devset tools development</tags>
    <copyright>Software Creations</copyright>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <iconUrl>http://kristjansson.us/favicon.ico</iconUrl>
    <dependencies>
      <dependency id=“fiddler” />
      <dependency id=“filezilla” />
      <dependency id=“winrar” />
      <dependency id=“sublime” />
      <dependency id=“gimp” />
      <dependency id=“dotpeek” />
      <dependency id=“grepwin” />
      <dependency id=“skype” />
      <dependency id=“testdriven.net” />
      <dependency id=“MagicDisc” />
      <dependency id=“winmerge” />
      <dependency id=“tortoisesvn” />
      <dependency id=“TortoiseGit” />
      <dependency id=“windowstelnet” />
    </dependencies>
    <releaseNotes>
    </releaseNotes>
  </metadata>
  <files>
    <file src=“tools\**” target=“tools” />
    <file src=“content\**” target=“content” />
  </files>
</package>

For this spec I have only dependencies which means I’m not really installing anything myself. Rather pulling and installing the dependencies. As such there is a /tool directory that has a PowerScript file that doesn’t do anything. Secondly since some of these packages have /content directory that needs to be created as well. If not an error will be thrown when the package is run ( that’s a bug ). There for I just put fake.txt file in that directory that is enough to get around the error.

My source can be found on GitHub

Since I don’t like doing tasks by hand that can be automated I created a nant script to create the package and push it up on the Chocolatey server. When I make a change to the package I save it and then on the command line just run the nant script.

For example
> nant -D:version=0.10

<?xml version=“1.0”?>

<!– Chocolatey fun –>
<project name = “SofwareCreateions.devset”
                 default = “PackAndDeploy”
                 basedir=“.”>

  <!–  Register the sys.* properties; most specifically, sys.env.* for all environment vars   –>
  <sysinfo failonerror=“false” />

  <!– The version number for the package –>
  <property name=“version” value=“0.01” dynamic=“true” overwrite=“true” />
  <property name=“BuildDrive” value=“${string::substring(project::get-base-directory(), 0, 1)}”  dynamic=“true” />
  <property name=“path.base.drive” value=“${BuildDrive}:\” />
  <property name=”cmdChocolateyPath” value=”${path.base.drive}\Chocolatey\bin\” />
  <property name=”cmdChocolatey” value=”chocolatey.bat” />
  <property name=”nugetFile” value=”softwarecreations.devset” />

  <!– This is the main / default target –>
  <target name=”PackAndDeploy” depends=”Start, UpdateVersion, Package, Deploy“>
    <echo message=”Done !“/>
  </target>

  <!– Individual targets below, those should NOT have any dependancies –>
  <target name=”Start” >
    <echo message=”*** Version number=${version} “/>

  </target>

  <!– Update version number –>
  <target name=”UpdateVersion” description=”Update version files to the current version being built.”  >
   
    <echo message=”*** Start updateVersions: ver=${version}“/>
   
    <!– Update NuGet package version –>
    <xmlpoke file=”softwarecreations.devset.nuspec” xpath=”/package/metadata/version” value=”${version}” />

  </target>

  <!– Package –>
  <target name=”Package“>
    <echo message=”Start Package:“/>

    <echo message=”Push to Nuget feed:“/>
    <!– Deploy to Nuget Gallery –>
    <exec program=”${cmdChocolateyPath}${cmdChocolatey}” verbose=”true
          commandline=”
pack ${nugetFile}.nuspec“/>
   
  </target>

  <!– Deploy –>
  <target name=”Deploy“>
    <echo message=”Start Deploy:“/>
   
    <exec program=”${cmdChocolateyPath}${cmdChocolatey}” verbose=”true
          commandline=”
push ${nugetFile}.${version}.nupkg“/>
   
  </target>

</project>

My package and it’s content can be found here If your have Chocolatey installed you can run it from the command line, like so.

> cinst SoftwareCreations.devset

Chocolatey is like apt-get on the Linux box, when you start using it its hard to go back to the manual search – webpage – download – install routine. There are only about 1200+ packages available at this point but that will grow going forward for sure.

Text to speech sample in C#

I found out that I had not played with Text to speech in .net yet. So naturally I went to take a look how easy or hard it is to use TTS in C#. It turns out the hardest part is to find the download link for the TTS install. Its hard to understand how Microsoft sometimes seems to hide download links. Once you find the SAPI SDK page, you would think they would have download links, but not so. However you do not need the whole SDK just to do Text to speech. You only need the TTS download which has a much smaller footprint. But again, where is the download link… ? I found one Microsoft page that doesn’t make it clear, and another third party page that I used to download the TTS install.

And now for the code it self, it’s very straight forward. After installing TTS add reference to your project, choose the COM “Microsoft Speech Object Library” that will create interop dll for your project. Add a reference to the speech library in code and the Hello world sample is only two lines of code.

using System;
//
using SpeechLib;

namespace tester
{
    class Program
    {
        static void Main(string[] args)
        {
            SpVoice myVoice = new SpVoice();
            myVoice.Speak(“Hello world”);
        }
    }
}

Another choice is to do the same without using the COM object, as COM is heavy. In that case add reference to System.Speech .net library and the code will look like this.

using System;
//
using System.Speech.Synthesis;

namespace tester
{
    class Program
    {
        static void Main(string[] args)
        {
            SpeechSynthesizer synth = new SpeechSynthesizer();
            synth.Speak(“Hello World”);
        }
    }
}

Non compliant XML in Configuration file Base64

I had a need to store some configuration data that is non XML compliant in my .net configuration file. As the configuration file is XML file I settled on storing the data in Base64 and then converting it back after it’s read from the configuration file. First we take the string and convert it to bytes then we convert the bytes to Base64 string that will be written to the configuration file. Reverse when you want to read the string from the configuration file.

And now for the code, as a UnitTest

// C#
string original = “&at;=@|”=’_EMPTY_'”;
// base64 value = JmF0Oz1AfCcnPSdfRU1QVFlfJw==

// to bytes and back test
byte[] dBytes = new System.Text.UTF8Encoding().GetBytes( original );
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
string str = enc.GetString(dBytes);
// compare
Assert.AreEqual( original, str);

// This is the string to put in the configuration file now Base64 formatted
string base64String = Convert.ToBase64String( dBytes );
// config string base64 value=JmF0Oz1AfCcnPSdfRU1QVFlfJw==
Console.WriteLine( “config string base64 value=”+ base64String );

// Convert Base64 back to a normal string, this needs to be done after reading
// the base 64 string from the config file
byte[] nonBase64bytes = Convert.FromBase64String( base64String );
// string from bytes
string fromBytes = new System.Text.UTF8Encoding().GetString(nonBase64bytes);
// Make sure it still adds up with the original
Assert.AreEqual(original, fromBytes );

Selenium browser UnitTesting from TeamCity

I just setup browser testing framework utilizing Selenium from TeamCity project. The usual suspects are involved, Gallio, MBUnit, Nant and even C# Unittests.

The usual scenario when it comes to automating browser testing is that the QA / testers will create some scripts to run a browser against your website. Somehow those tests are usually not maintained very well and often are run by hand. There is not much value in browser testing scripts if you have to run them by hand.

As I needed browser testing on one of the projects I’m on I decided to look into using more of a automated setup to run the browser tests. There seem to be two big players Waitn and Selenium, Selenium lends itself to broader range of testing, naturally we will go with Selenium.

Here is the scenario I want, the tester installs a recorder on his computer, in this case a FireFox plugin. The tester records the tests and runs them in the browser using the plugin tool. Once the tester is happy with the tests the tester checks them into the repository. After check-in tester lets a developer know that there are new or changed tests. The developer takes the script and turns it into C# UnitTest, simply has Selenium convert it to UnitTest code. Then the developer takes and updates or adds the tests that resulted from the scripts and checks it into the repository. The conversion step could be automated in the future once Selenium supports that. The next step is to run it from TeamCity and after it runs you get email with the results.

So let’s take a closer look at what is needed. We need the UnitTest to be able to run against different servers using different browsers. We will pass values from TeamCity to the Nant script that is responsible for compiling and running the tests. This is how your test C# configuration file might look like.

<!– Selenium RC properties–>
    <add key=“SeleniumAddress” value=“localhost” />
    <add key=“SeleniumPort” value=“4444” />
    <add key=“SeleniumSpeed” value=“0” />
   
    <!– Browser targets –>
    <add key=“BrowserType” value=“*firefox” />
    <add key=“BrowserUrl” value=“http://10.9.169.198/” />
    <add key=“BaseUrlPath” value=“IPCA.Dev/” />

Then the base test class will look something like this.

[FixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            // Read from config
            msBrowserType = getConfigSetting(“BrowserType”, msBrowserType );
            msBrowserUrl = getConfigSetting(“BrowserUrl”, msBrowserUrl);
            msBasePath = getConfigSetting(“BaseUrlPath”, msBasePath);
            //
            msSeleniumAddress = getConfigSetting( “SeleniumAddress”, msSeleniumAddress );
            miSeleniumPort = int.Parse(getConfigSetting(“SeleniumPort”, miSeleniumPort.ToString()) );
            msSeleniumSpeed = getConfigSetting( “SeleniumSpeed”, msSeleniumSpeed );
           
           
            // Start up the selenium session, using config values
            selenium = new DefaultSelenium(msSeleniumAddress, miSeleniumPort, msBrowserType, msBrowserUrl);
            selenium.Start();
            // Clean errors
            verificationErrors = new StringBuilder();

            // sets the speed of execution of GUI commands
            selenium.SetSpeed(msSeleniumSpeed);
        }

        [TearDown]
        public void TeardownTest()
        {
            try
            {
                selenium.Stop();
            }
            catch (Exception)
            {
                // Ignore errors if unable to close the browser
            }
            Assert.AreEqual(“”, verificationErrors.ToString());
        }

And a sample Selenium C# Unittest

//
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
//
using Gallio.Framework.Assertions;
using MbUnit.Framework;
//
using Selenium;

namespace SeleniumTests
{
    [TestFixture]
    public class LoginPage : WebTestBase
    {

        [Test]
        public void TheLoginPageTest()
        {
            selenium.Open( this.msBasePath + “TestLogin.aspx”);
            selenium.Click(“lbAdmin”);
            selenium.WaitForPageToLoad(“50000”);
            selenium.Click(“loginLink”);
            selenium.WaitForPageToLoad(“50000”);
            try
            {
                Assert.IsTrue(selenium.IsTextPresent(“my responsibilities regarding permissible access”));
            }
            catch (AssertionException e)
            {
                verificationErrors.Append(e.Message);
            }
            selenium.Click(“ctl00_pageContent_btnSubmit”);
            selenium.WaitForPageToLoad(“50000”);
            try
            {
                Assert.IsTrue(selenium.IsTextPresent(“Total Unassigned Web”));
            }
            catch (AssertionException e)
            {
                verificationErrors.Append(e.Message);
            }
        }
    }
}

After the Nant script compiles the tests and is getting ready to run the UnitTests it needs to startup the Selenium engine. Make sure to spawn in order for the Selenium engine to exist on another thread than your tests.

<property name=“SeleniumExec” value=“java” />
  <property name=“SeleniumPath” value=“C:\apps\selenium\selenium-server-1.0.3\” />
  <property name=”SeleniumParams” value=”-jar ${SeleniumPath}selenium-server.jar” />

    <!– Start selenium –>
    <exec   program=”${SeleniumExec}
      commandline=”
${SeleniumParams}” workingdir=”${path.base}${WebTest}
      spawn=”
true” failonerror=”true” verbose=”true
       />

    <!– Give it a sec to load –>
    <sleep milliseconds=”3000” />

In order to run the tests using different browsers, change the configuration file of the tests before run.

<!– Run tests in Firefox browser –>
    <xmlpoke
        file=“${path.base.test}${assembly.test.config}”
        xpath=“/configuration/appSettings/add[@key=’BrowserType’]/@value”
        value=“*firefox”
        verbose=“true”/>

    <call target=“runTests” />

<target name=“runTests”
    description=“runs tests using Gallio.” >

   
    <echo message=“*** Start runTests: “/>

      <gallio
        result-property=“exitCode”
        failonerror=“false”
        report-types=“Html;Xml”
        report-directory=“${artifacts}”
        report-name-format=“gallioresults”
        show-reports=“false”
        application-base-directory=“${path.base.test}”
            >

          <!– Specify the tests assemblies  –>
          <files>
            <include name=“${path.base.test}${assembly.test}”/>
          </files>
        </gallio>

        <!–
            Set error for email injector to pick it up and GlobalFailBuildMessage for
            the end target to fail the build after cleanup
          –>

        <if test=“${int::parse(exitCode)!=0}”>
          <property name=“GlobalFailBuildMessage” value=“*** One or more tests failed. Please check the log for more details” dynamic=“true” />
          <echo message=“EmailInjectMsg=${GlobalFailBuildMessage}” />
        </if>

    <echo message=“*** End runTests: “/>
  </target>

And after the run of the Unittests Selenium needs to be shut down

<!– Stop Selenium server –>
      <get  src=“http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer”
        dest=“shutdown.txt”  failonerror=“false”
      />

As I had a need to setup different configurations in TeamCity to run against different locations on the webserver I used a couple of Nant variables that are passed on the command line from TeamCity, like you normally would do when running Nant script -D:BaseUrlPath=/Test/ etc.

<echo message=“*** Location variables passed from TeamCity”/>
    <echo message=“*** BrowserUrl=${BrowserUrl} “/>
    <echo message=“*** BaseUrlPath=${BaseUrlPath} “/>

Of course you get the Gallio UnitTest report as well

gallio_report

With this setup once we deploy to a server we can run all the browser tests on it using different browsers with one click of a button from TeamCity.

Custom file extenstion in Visual Studio C#

I was using some files that have among other things some C# code in it in VS. When it dawned at me that I wasn’t getting the syntax highlighting which makes it much harder to read the code. Visual Studio just treats it as any other text file. In order to add a new one you just need to set new file association within VS. Tools – Options – Text editor – File Extensions. Add your extension and the editor you want to use, in my case Microsoft Visual C#. That will give you the code syntax, much better.