Showing posts with label compact framework. Show all posts
Showing posts with label compact framework. Show all posts

Friday, December 11, 2009

Unit Testing With Compact Framework and Visual Studio

Following up my issue with running NUnit tests for the Windows Mobile application, I came across a couple of articles on using the unit testing framework integrated in Visual Studio 2008 which is now supposed to be user friendly.
The process starts with selecting the function name, right-clicking on it and selecting "Create Unit Tests"

I can select the functions I want unit tests to be created for - I'll only choose one for now

I am then prompted for the name of the project where my tests will be created. Visual Studio adds a new project to the solution and this is the code for the test method created for the function I chose.


///
///A test for CreateDatabase
///

[TestMethod()]
public void CreateDatabaseTest()
{
DataBase target = new DataBase(); // TODO: Initialize to an appropriate value
target.CreateDatabase();
Assert.Inconclusive("A method that does not return a value cannot be verified.");
}

This is great, except that I want to test for the things I want to test. So, of course, I need to change that. That's probably closer to what I want to test in my method:


[TestMethod()]
public void CheckDatabaseCreation()
{
DataBase target = new DataBase();
target.SetFileName(@"\Program Files\TestDB\TTrack.sdf");
target.SetConnectionString(@"Data Source=\Program Files\TestDB\TTrack.sdf");
target.DeleteDatabase();
target.CreateDatabase();
target.RunNonQuery(target.qryInsertRecord);
int count = target.RunScalar(target.qryCountUsers);
Assert.AreEqual(count, 1);
}

This is not so much different from the way tests are created in NUnit. In fact, so far there is no difference at all. Now, to run the test. There is a menu item "Test" in the top menu where I can select Test->Windows->Test View and the "Test View" becomes visible.

There I can see my tests - the auto generated one and the one I added myself.


I can run all tests or select any combination of tests I want to run from the Test View and choose either "Run Selection" or "Debug Selection" (I did not find out yet what the difference is - if I place a breakpoint inside the test method and choose "Debug Selection", the execution does not break at the breakpoint). After the test(s) finished running, I can see the result in the Test Results window.

by . Also posted on my website

Tuesday, November 24, 2009

Compact Framework and NUnit

I have the idea of a small application I could write for the Windows Mobile. The application will only use its local SQL Server database, at least initially, and it is really simple to create a local database on the device. The only things I need are the physical location of the sdf file on the device and the connection string.

In my "DataBase" class I generate them

private string GetLocalDatabasePath()
{
string applicationPath = Path.GetDirectoryName(this.GetType().Assembly.GetName().CodeBase);
string localDatabasePath = applicationPath + Path.DirectorySeparatorChar +
"TTrack.sdf";
return localDatabasePath;
}

private string GetLocalConnectionString()
{
string localConnectionString = "Data Source=" +
GetLocalDatabasePath();

return localConnectionString;
}

To create a database I just check if the database file already exists, and if not - I create it. Also, for testing purposes, the delete database function is used.

internal void CreateDatabase()
{
if (!File.Exists(localDatabasePath))
{
using (SqlCeEngine engine = new SqlCeEngine(localConnectionString))
{
engine.CreateDatabase();
}

RunNonQuery(qryCreateTables);
}
}

internal void DeleteDatabase()
{
string dbPath = GetLocalDatabasePath();
if (File.Exists(dbPath))
{
File.Delete(dbPath);
}
}

The RunNonQuery bit is just the creation of tables in the database.

internal void RunNonQuery(string query)
{
string connString = GetLocalConnectionString();

using (SqlCeConnection cn = new SqlCeConnection(connString))
{
cn.Open();
SqlCeCommand cmd = cn.CreateCommand();
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
}

The query for now just creates the simplest possible "dummy" table

internal string qryCreateTables = "CREATE TABLE Users (" +
"UserID uniqueidentifier PRIMARY KEY DEFAULT NEWID() NOT NULL, " +
"Name NVARCHAR(50) NOT NULL )";

The RunScalar, obviously, is used to run ExecuteScalar(). Some refactoring still required to improve the code.

internal int RunScalar(string query)
{
string connString = GetLocalConnectionString();

using (SqlCeConnection cn = new SqlCeConnection(connString))
{
cn.Open();
SqlCeCommand cmd = cn.CreateCommand();
cmd.CommandText = query;
return int.Parse(cmd.ExecuteScalar().ToString());
}
}

Now that I can create a database, I can run this simple bit of code to see if it is working.

DataBase db = new DataBase();
db.CreateDatabase();
db.RunNonQuery(db.qryInsertRecord);
MessageBox.Show(db.RunScalar(db.qryCountUsers).ToString());

Database gets created, a record gets inserted, a messagebox with "1" is shown. All is well.

Next, I decide to quickly create and run a simple test for database creation: If the database is present, I delete it, then create a new one, insert one record and test for the count of records indeed being one.

Here is the test I write in NUnit.

[Test]
public void CheckDatabaseCreation()
{
DataBase db = new DataBase();
db.SetFileName(@"\Program Files\TestDB\TTrack.sdf");
db.SetConnectionString(@"Data Source=\Program Files\TestDB\TTrack.sdf");
db.DeleteDatabase();
db.CreateDatabase();
db.RunNonQuery(db.qryInsertRecord);
int count = db.RunScalar(db.qryCountUsers);
Assert.AreEqual(count, 1);
}

This does not go as well, however:

What happened there? Oh, of course - the NUnit test runs on the desktop, but the code is supposed to run on the emulator (I don't use the actual device yet). So, it looks like I will have to work on the approach to testing ...

by . Also posted on my website

Thursday, November 19, 2009

Compact Framework and forms management.

This was my first experience with the Microsoft Compact Framework. The application is developed in Visual Studio 2005 and is targeted to run on Pocket PC 2003 devices. Basically, I had to extend a simple application that had only one form to add some functionality and a few more forms. I understand that the forms in Compact Framework are treated a bit differently compared to a desktop application. What to use for navigation between forms, Show() or ShowDialog()? I decided to use Show() because I have only about 5 forms, most of those are very simple and also, my application will be the only one running on the device. So I thought, if I create each form once and keep them all in memory, just showing and hiding them, it may use more memory, which I do not care that much about, but be easier on the device battery. Okay, I may be saying total nonsense here - I have about 7 days Compact Framework development experience at this very moment.

So I have a dictionary where all existing forms are kept.

private static Dictionary _applicationForms = new Dictionary();

And the function that gets the form from the dictionary by name.

internal static Form GetFormByName(string formName)
{
if (_applicationForms.ContainsKey(formName))
{
return _applicationForms[formName];
}
else
{
Form newForm = CreateFormByName(formName);
AddFormIfNotExists(newForm);
return newForm;
}
}

And the function to create a form if it has not been yet created.

private static Form CreateFormByName(string name)
{
Form form = new Form();

switch (name)
{
case Constants.frmFirst:
form = new frmFirst();
break;

...

case Constants.frmLast:
form = new frmLast();
break;
default:
form = new frmLast();
break;
}
return form;
}

And the function to add the form to the dictionary if it is not there.

internal static void AddFormIfNotExists(Form frm)
{
if (!_applicationForms.ContainsKey(frm.Name))
{
_applicationForms.Add(frm.Name, frm);
}
}

And when I need to show another form, I get it from the dictionary and show, and hide the current form.

internal static void ShowFromForm(Form source, string targetName)
{
Form frm = GetFormByName(targetName);
frm.Show();
source.Hide();
}

There's a bit more to it, sometimes I need to find which form is currently visible etc, but these are the core things. Stupid? Good enough? I don't know ...

by . Also posted on my website