Friday, October 24, 2008
Note that my blog has moved to http://www.pksoftware.net/devblog/.

Just a reminder, I am still getting a lot of hits on this one....

Blog moved to: http://www.pksoftware.net/devblog/

:-)

Friday, October 24, 2008 11:15:55 AM (GMT Standard Time, UTC+00:00) |  |  |  |  |  |  |  |  |  |  |  |  |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Wednesday, October 31, 2007
Note that my blog has moved to http://www.pksoftware.net/devblog/.
It's common practice for developers to make small "TODO" notes in code as they work for themselves or others to clarify at some time...

// TODO: confirm this business requirement...
// TODO: make this better!
// TODO: bread, butter, eggs and milk...

Issues can arise when the TODO's are not taken care of for whatever reason or get lost in the mayhem of meeting deadlines. A worst case scenario could arise when there is a production defect for an obscure situation and the maintenance programmer finds something like this:

// TODO: Not sure if there are any more response codes for this one, check before release.

Opps! Now that's expensive.
Now I am not saying this is good or bad (!) practice - but what I have started to do within my team is create either a failing or ignored unit test (depending on the importance) marking what would normally be an innocent "TODO" item. The unit test stays in the build as either a fail or ignore and does not drop off the radar.

[Test]
public void Need_to_confirm_foo()
{
  Assert.Fail();
}

Or...

[Test]
[Ignore("Confirmation required from the business")]
public void A_foo_only_has_a_bla()
{
}

It's much harder to miss a bunch of ignored or failing unit tests before that production release than some well hidden TODO comments!

 

Wednesday, October 31, 2007 9:40:05 AM (GMT Standard Time, UTC+00:00) |  |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Tuesday, September 04, 2007
Note that my blog has moved to http://www.pksoftware.net/devblog/.

Make that version 1.0.0.3!

I did not quite get this feature into the previous version and just posted the updates in case I got busy.

The big (and very useful) change for build 3 is that you can "paste" unit test code into the tool and the phrases will be extracted - if they use underscores and the code is C# (sorry, minor bug, I'll fix that shortly!) In practice I have found the underscore styke far more readable.

For example, if you have the following unit test code, copy it to the clipboard...

namespace Tests
{
    [TestFixture]
    public class PersonEntityTests
    {
        [SetUp]
        public void TestSetUp()
        {
            // ...
        }
        
        [Test]
        public void A_method_will_be_extracted_from_the_clipboard()
        {
            // asserts etc
        }
    }
}

...and use the new "Paste beaviours from clipboard" menu option (or ALT+F5) and you get the method name extracted.

The full round trip. Whe you want to continue working on a unit test class you can use this feature to get the current context of the testing... have fun! PK :-)

  http://www.pksoftware.net/BehaviourToUnitTest/


Quick note - now at v1.0.0.2 - the main changes are:
  • The use of the ICSharp.TextEditor for better editing
  • The defaults are C# with the underscore style
  • A few more word substitutions by default

Enjoy!

Tuesday, September 04, 2007 10:49:31 AM (GMT Standard Time, UTC+00:00) |  |  |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Monday, August 27, 2007
Note that my blog has moved to http://www.pksoftware.net/devblog/.

I have uploaded a small development tool that I put together recently, its called "Behaviour to Unit Test". Basically it converts code functionality from plain sentences (or stories) into unit test stub code. You could also think of it as a cure for TDD writers block!

For an example of the usage, use the Generation -> Fill out example menu option and hit Convert. Basically it takes a set of plain language behaviours for an object such as "person":

  • Check that the default values of all string properties are empty
  • The ToString method renders the first and last names
  • If the date of birth is null, calculate age will return -1
  • If the date of birth is not null, calculate age will return a value

...and converts them into something like:

using System;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;

namespace Tests
{
    [TestFixture]
    public class PersonEntityTests
    {
        private PersonEntity person;
        
        [SetUp]
        public void TestSetUp()
        {
            person = new PersonEntity();
        }
        
        [Test]
        [Ignore("Currently only a unit test stub")]
        public void CheckThatTheDefaultValuesOfAllStringPropertiesAreEmpty()
        {
        }
        
        [Test]
        [Ignore("Currently only a unit test stub")]
        public void TheToStringMethodRendersTheFirstAndLastNames()
        {
        }
        
        [Test]
        [Ignore("Currently only a unit test stub")]
        public void IfTheDateOfBirthIsNullCalculateAgeWillReturnMinus1()
        {
        }
        
        [Test]
        [Ignore("Currently only a unit test stub")]
        public void IfTheDateOfBirthIsNotNullCalculateAgeWillReturnAValue()
        {
        }
    }
}

There are C# and VB.NET templates for now. Check it out:

  http://www.pksoftware.net/BehaviourToUnitTest/

My intention is to keep the tool small and simple. The main thing I want to add at the moment is some load/save functionality and drop in the ICSharp.TextEditor for more friendly editing...

Monday, August 27, 2007 9:43:04 AM (GMT Standard Time, UTC+00:00) |  |  |  |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Thursday, July 19, 2007
Note that my blog has moved to http://www.pksoftware.net/devblog/.

This is just a quick heads up to say that I think the Castle Project rocks!

I have been using it allot of late especially Active Record. I'll blog more detail later but it's what I have been looking for all these years! Many time I have implemented simple subsets of the functionality that Castle provides to help get the job done. Castle wraps up all those funky framework fragments and more with a great "action pack" flavour to it in the form of Mono Rail (i.e. 'ruby on rails' for .Net)

Very cool  ;-)

Thursday, July 19, 2007 11:21:35 AM (GMT Standard Time, UTC+00:00) |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Wednesday, June 13, 2007
Note that my blog has moved to http://www.pksoftware.net/devblog/.

Just a quick note that could drive you completely mad if you were not aware...

If you are using NUnitForms for testing your GUI and have code in the forms "Shown" event, it will not run unless you follow the Form.Show call with Application.DoEvents(), see sample code below

This example is just a Label (label1) dumped on a Form with the Load and Shown events updating the label with the respective event text:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace NUnitFormsDemo1
{
    public partial class ShownTestForm : Form
    {
        public ShownTestForm()
        {
            InitializeComponent();
        }

        private void ShownTestForm_Load(object sender, EventArgs e)
        {
            label1.Text = "Load";
        }

        private void ShownTestForm_Shown(object sender, EventArgs e)
        {
            label1.Text = "Shown";
        }
    }
}

Here is some sample NUnitForms test code, the first test asserts that after the Form.Show call the label text is "Load" and the second test shows that the label text is "Shown".

using System;
using System.Windows.Forms;
using NUnit.Framework;
using NUnit.Extensions.Forms;

namespace NUnitFormsDemo1.UnitTests
{
    [TestFixture]
    public class TestFormShownIssue : NUnitFormTest
    {
        [Test]
        public void TestFormShow()
        {
            ShownTestForm frm = new ShownTestForm();
            LabelTester label1Tester = new LabelTester("label1");
            frm.Show();
            Assert.AreEqual("Load", label1Tester.Text);
        }

        [Test]
        public void TestFormShowWithDoEvents()
        {
            ShownTestForm frm = new ShownTestForm();
            LabelTester label1Tester = new LabelTester("label1");
            frm.Show();
            Application.DoEvents(); // allows the 'Shown' event to fire
            Assert.AreEqual("Shown", label1Tester.Text);
        }
    }
}

I will take an educated guess that this is due to the GUI message pump etc.

In general if I come across this any of this type of unexpected behavior with NUnitForms I will try a DoEvents before tearing my hair out.

Wednesday, June 13, 2007 9:30:07 AM (GMT Standard Time, UTC+00:00) |  |  |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Tuesday, March 20, 2007
Note that my blog has moved to http://www.pksoftware.net/devblog/.

My blog has moved to:
 
http://www.pksoftware.net/devblog/

This post now at:
 
http://www.pksoftware.net/devblog/post/2007/03/Working-With-Unsupported-Controls-In-NUnitForms.aspx

 

Another sequel to the entry on "Getting Started with NUnitForms"
  http://www.pksoftware.net/blog/2007/02/06/Getting+Started+With+NUnitForms.aspx
This post is focused on compiling the latest NUnitForms code from sourceforge.

I have seen/heard/had a few questions about testing windows forms controls that are not currently supported by NUnitForms (specifically ".Net 2.0 NUnitForms alpha 5 release" - http://sourceforge.net/project/showfiles.php?group_id=95656).

There are 2 answers...

  1. Cut your own (see the "How to add Control Testers" section at http://nunitforms.sourceforge.net/docs.html), or
  2. Get the latest source out of the subversion repository and use the generic tester class...
The subversion connection details are here: http://sourceforge.net/svn/?group_id=95656

You will need TortoiseSVN (http://tortoisesvn.net/) or similar to get the files.



Note that all related files for the build are also downloaded (nant, nunit, ncover and ndoc etc) so there won’t be any messing around trying to find the correct library dependencies (ahhh!) Of course, because of this the download is about 8.5mb...

Now... from here on in things could get a little messy. You could have problems with key containters, there may be a duplicate "ButtonTestser.cs" file... The list was getting a little long - the short answer to the "problems" were to compile the NUnitForms project after modifying the signing method of the 2 projects "NUnitForms" and "NUnitForms.ScreenCapture". You will also need to delete the AssemblyKeyName code references in the relevent AssemblyInfo.cs files.



Keep in mind that when you get the latest out of a code repository this sort of thing is not unexpected or "bad". Its a work in progress...

Now the latest build of the NUnitForms DLL will give you access to the generic control tester class. When you need to test a control that does not have its own tester class (e.g. ButtonTester) you can use the generic declaration and create your own tester class, e.g. for a picture box:


public class PictureBoxTester : ControlTester<PictureBox, PictureBoxTester>
{
  // Now implement each overloaded constructor calling the base class
  public PictureBoxTester() {}
  public PictureBoxTester(string name, Form form) : base(name, form) {}
  public PictureBoxTester(string name, string formName) : base(name, formName) {}
  public PictureBoxTester(string name) : base(name) {}
  public PictureBoxTester(ControlTester tester, int index) : base(tester, index) {}
}



Now in the tests you can create tester objects and access all the properties and perform clicks etc:

[Test]
public void ExamplePropertyCheckAndDoubleClickTest()
{
  PictureBoxTester picTester = new PictureBoxTester("pictureBox1");
  Assert.AreEqual(@"C:\dir\somePic.bmp", picTester.Properties.ImageLocation);
  picTester.DoubleClick();
}


Easy as pie right?! Well sort of. But much easier than writing your own windows forms GUI testing framework!!

PK  ;-)

Tuesday, March 20, 2007 12:32:20 PM (GMT Standard Time, UTC+00:00) |  |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Monday, February 12, 2007
Note that my blog has moved to http://www.pksoftware.net/devblog/.

My blog has moved to:
 
http://www.pksoftware.net/devblog/

This post now at:
 
http://www.pksoftware.net/devblog/post/2007/02/Getting-Started-With-NUnitForms-GUI-Testing-With-Message-Boxes.aspx

 

A sequel to the entry on "Getting Started with NUnitForms"
  http://www.pksoftware.net/blog/2007/02/06/Getting+Started+With+NUnitForms.aspx
This post is focused on handling the testing of message boxes in an application.

Another common test requirement that you will probably come across in the GUI world is the use of message boxes. To handle a message box with NUnitForms (i.e. simulate a user click or similar), use a "message box handler" method. Firstly set up the test to "expect" a message box and then supply the name of the method to handle the reaction:

[Test]
public void MessageBoxTest()
{
   base.ExpectModal("Info", "MessageBoxTestHandler");
  ButtonTester runButton = new ButtonTester("RunButton");
  runButton.Click();
}

This tells the test sub-system that a message box is expected and the title should be "Info". Also supplied is the name of a handling method - in this case "MessageBoxTestHandler". This method should create a "MessageBoxTester" and (most likely) click the OK button:

public void MessageBoxTestHandler()
{
  MessageBoxTester messageBox = new MessageBoxTester("No Item Selected");
  messageBox.ClickOk();
}

Other useful methods of the MessageBoxTester class are "ClickCancel" and "SendCommand(cmd)" where "cmd" is an enum value of type MessageBoxTester.Command:
  • OK
  • Cancel
  • Abort
  • Retry
  • Ignore
  • Yes
  • No
  • Close
  • Help
For example:

public void MessageBoxTestHandler()
{
  MessageBoxTester messageBox = new MessageBoxTester("Cancel, are you sure?");
  messageBox.SendCommand(Command.Yes);
}

A practical application of this could be tests where for example if search criteria is not supplied a "no criteria" message box is displayed. Boundary checks in methods are common places for bugs to occur so make sure you perform the same boundary check on the GUI layer!
Monday, February 12, 2007 12:19:41 PM (GMT Standard Time, UTC+00:00) |  |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Tuesday, February 06, 2007
Note that my blog has moved to http://www.pksoftware.net/devblog/.

My blog has moved to:
 
http://www.pksoftware.net/devblog/

This post now at:
 
http://www.pksoftware.net/devblog/post/2007/02/Getting-Started-With-NUnitForms.aspx

 

An introduction to NUnitForms with a basic example of automated Microsoft .Net Windows Forms Testing using NUnit.

NUnitForms is a lesser known extension to the well known NUnit testing framework. See http://nunitforms.sourceforge.net/ for details and downloads. It is currently in the process of being upgraded from .Net Framework V1.1 to V2.0 and is only being distributed as an MSI with no source code (except via CVS as Adam pointed out below).

I have found it quite useful but the documentation was lacking and the learning curve a bit painful, hence this post! I will assume that you have NUnit and NUnitForms installed for the following code samples to run.

How can NUnitForms be used?

NUnitForms gives a developer the ability to approach forms development from a test first perspective, or to simply provide a reliable set of automated regression tests for a user interface. (For the record, I am not getting into concepts such as model-view-controller/presenter, interface coding or the like - all I am demonstrating is how to use NUnitForms for testing.)

NUnitForms replaces (or supplements) the traditional “GUI test harness” method commonly used for GUI development. Sometime the use of even a test harness is bypassed (because of time restrictions of course!) The problem with manual test harnesses are that the typically become a mess that only the original developer can even make sense of and, all the testing is done manually. NunitForms alleviates these issues by making things automated in the first place. I am not against the use of a manual GUI test harness - they still have their benefits - but compared to automated testing they lose out big time. A useful GUI test harness example that would be hard to test in an automated fashion is control resize behaviour and positioning.

How does it work?

Basically there is a lot of reflection and forms/controls parsing to locate controls and invoke the methods that are normally performed by the user, such as pushing a button. For example, a test uses NUnitForms code that fires the “OnClick” event for a button. You put together a series of these events simulating a user and you have an automated script. That’s putting it really simply!

A Simple Example

Get a new instance of VS.Net going. I created a basic form as below:

The textbox and button are named “NameTextbox” and “RunButon” respectively (more on that later).

Add a new project for the unit testing - add references to:

  • The windows application we are testing
  • NUnit
  • NUnitForms
  • System.Windows.Forms

See sample solution setup below:

Now define a test fixture as normal (with the addition of the NUnit.Extensions.Forms using directive) but there are 2 main differences:

  • the fixture needs to inherit from “NUnitFormTest” and to get the test to work at all.
  • we need to override the “Setup” method. In this setup method we create an instance of the form and show it.

Make sure you show it or you will go crazy trying to debug the problem (yes I forgot!) The setup method is called before each test so we start with a clean slate.

Now for a test. This is a dumb test, but remember we are looking at the concept!

When I push the “Run” button, I want whatever test is in the textbox to become the form title, sample test:

We need a TextBoxTester and a ButtonTester. This will give us access to the button and textbox on the form. Assign a value to the textbox and invoke a “click” on the button. Now for the test, we have a reference to the test form at the fixture level so we can get the form title from there.

using System;
using NUnit.Framework;
using NUnit.Extensions.Forms;

namespace NUnitFormsDemo1.UnitTests
{
    [TestFixture]
    public class SimpleFormTests : NUnitFormTest
    {
        SimpleForm _simpleForm;

        public override void Setup()
        {
            _simpleForm = new SimpleForm();
            _simpleForm.Show();
        }

        [Test]
        public void FillTextboxWithData()
        {
            TextBoxTester nameTextbox = new TextBoxTester("NameTextbox");
            ButtonTester runButton = new ButtonTester("RunButton");
            string expected = "From automated test.";
            
            Assert.AreEqual("Simple Form", _simpleForm.Text, "Initial value incorrect.");
            nameTextbox["Text"] = expected;
            runButton.Click();
            Assert.AreEqual(expected, _simpleForm.Text, "Title should be that textbox value.");
        }
    }
}

The test failed.

TestCase 'NUnitFormsDemo1.UnitTests.SimpleFormTests.FillTextboxWithData'
failed: Title should be that textbox value.
String lengths differ. Expected length=20, but was length=11.
Strings differ at index 0.
expected: <"From automated test.">
but was: <"Simple Form">

Now implement the code to pass the test. Here is the rocket science code back in the form:

private void RunButton_Click(object sender, EventArgs e)
{
    this.Text = NameTextbox.Text;
}

Hey - I can do that without NUnitForms!

That particular test yes - with some changes to the sample form itself. The controls would need to be exposed either via a property or similar and the button click can be simulated with the “PerformClick” method. However that calls for exposing controls via properties etc which means alot more coding and to be honest we are just scratching the surface of what NUnitForms can do. The use of NUnitForms allows us to avoid that sort of "coding simply to support testing".

I hope that can get you started, more to come... PK :-)

kick it on DotNetKicks.com

Demo Source: NUnitFormsDemo1.zip (12.83 KB)


More Forms Testing:

 

Tuesday, February 06, 2007 2:30:47 PM (GMT Standard Time, UTC+00:00) |  |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Tuesday, January 09, 2007
Note that my blog has moved to http://www.pksoftware.net/devblog/.

At some point in the unit testing game you will need to tackle the unpleasant task of actually coding and running unit tests on the data access code. This in itself can open a bit of a can of worms - the bigger the database, the more worms you need to deal with. If you want a quick solution to being able to run a bunch of data access tests that insert, update and delete data in tables - try putting a TransactionScope object at the test fixture level. If the scope is not committed the changes are not stored, perfect scenario for a group of unit tests.

Marcus Rosen prompted the idea and I have been using this technique against a local copy of an MSSQL database and have had no issues to date. It has simplified the development process in that data does not keep disappearing due to my unit tests clearing tables and inserting test items.

I have seen "Rollback" attributes around (such as http://weblogs.asp.net/rosherove/archive/2004/10/05/238201.aspx) but the above solution is a one liner and requires no new libraries, and integration etc.

I like a simple solution  ;-)


MSDN TransacrionScope Help:
http://msdn2.microsoft.com/en-us/library/system.transactions.transactionscope.aspx

Tuesday, January 09, 2007 12:50:19 PM (GMT Standard Time, UTC+00:00) |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Thursday, December 21, 2006
Note that my blog has moved to http://www.pksoftware.net/devblog/.

I came across this a while ago and forgot to post… James Shore is putting together what basically looks like a “how to get agile” guide. The book chapters are posted fairly frequently for review. Looks like a good read.

http://www.jamesshore.com/Agile-Book/

Thursday, December 21, 2006 12:23:29 PM (GMT Standard Time, UTC+00:00) |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Monday, December 11, 2006
Note that my blog has moved to http://www.pksoftware.net/devblog/.

Updated - See http://www.pksoftware.net/blog/2007/02/06/Getting+Started+With+NUnitForms.aspx


I have not had a huge look at this yet but a not so known spin off from NUnit:

http://nunitforms.sourceforge.net/

Unit testing geared towards .Net WinForms applications...

Monday, December 11, 2006 11:32:32 AM (GMT Standard Time, UTC+00:00) |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Monday, November 27, 2006
Note that my blog has moved to http://www.pksoftware.net/devblog/.

With test driven, I take the "standard" TDD approach (something like):

  • write test (based on a use case etc)
  • build the app (will fail because code is not there etc)
  • implement code the code required to get the build compiling
  • run test (test will fail becasue the code stub does nothing useful)
  • implement code - run test and repeat until passed
  • refactor as required - run tests

Then apply then to Visual Studio 2005... The results of following this procedure need to be experienced to really understand the benefits if you are not farmiliar with TDD etc.

I also make use to a couple of manually created keyboard shortcuts, Ctl+ALT+T and Ctl+ALT+R which
execute TestDriven.NET's "Run Test(s)" and "Repeat Test Runs" context menu options respectively.

Here is my TDD with TestDriven.NET and VS.Net 2005's handy smart menus and refactoring capabilities:

  • Create the class stub if its the first test for the class
    (I find the compiler telling me that I am missing a class kind of superfluous, I still follow this process sometimes about 50-50)
  • Write test (based on a use case etc)
  • Before I build the application, I normally know which methods are missing so instead of performing failing build I use the smart menu to generate the stub for me (use the shortcut keys Shift+ALT+F10, then enter)
  • Run the test with Ctl+ALT+T (TestDriven.NET will perform a build as required, the test will - or should - fail because the code stub does nothing useful)
    Use the "Escape" key to get out of the "Output" window after a test run.
  • Implement enough code to pass the test - run test and repeat until passed using Ctl+ALT+R to execute the "Repeat Test Runs" option.
    Again, use the "Escape" key to get out of the "Output" window after a test run.
  • Refactor as required - run tests (Ctl+ALT+R)

Following this procedure helps me keep the focus on the requirements in a very efficient manner with minimal flicking between windows, initiating builds etc.

Monday, November 27, 2006 12:45:24 PM (GMT Standard Time, UTC+00:00) |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Thursday, November 23, 2006
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Using the InternalsVisibleTo attribute to get access to another classes internal methods for testing.
Thursday, November 23, 2006 12:42:08 PM (GMT Standard Time, UTC+00:00) |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Tuesday, November 21, 2006
Note that my blog has moved to http://www.pksoftware.net/devblog/.

Jamie has put together a nice screencast of some of TestDriven.NET's new features, check it out:

http://weblogs.asp.net/nunitaddin/archive/2006/11/11/Testing-With-NCover_2F00_NCoverExplorer.aspx

Tuesday, November 21, 2006 10:11:13 AM (GMT Standard Time, UTC+00:00) |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Thursday, November 16, 2006
Note that my blog has moved to http://www.pksoftware.net/devblog/.

When I first started trying out TDD and (more so when I started using the TestDriven.Net), I still spend a good chunk of my test development time stepping through the code line by line, checking the state of variable etc. It took me a while to kick the habit, but when you get stuck into TDD you won't be spending anywhere near as much time stepping through your code trying to work out what’s going wrong as you probably used to.
Why? Because the unit tests you write in an incremental fashion, build slowly on the last and in turn your confidence in the code is greater – you no longer feel the need to step through the code. When I run a test that fails now I can usually spot the issue relatively quickly without having to "step in". Those small TDD steps really pay off.
Don't get me wrong, I still step into my code when I get a curly one, but it's more the odd occasion now than the natural response.
Stay out of that debugger - it will save you a lot of time :-)
Thursday, November 16, 2006 9:46:13 AM (GMT Standard Time, UTC+00:00) |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Monday, November 13, 2006
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Why would anyone have a problem paying a (small amount) for a great piece of productivity software? Jamie Cansdale has been copping flack about making TestDriven.Net a commercial product...
Monday, November 13, 2006 9:39:55 AM (GMT Standard Time, UTC+00:00) |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Friday, November 10, 2006
Note that my blog has moved to http://www.pksoftware.net/devblog/.
NCover Explorer is one of my "Must Have Apps"...
Friday, November 10, 2006 9:45:53 AM (GMT Standard Time, UTC+00:00) |  |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Thursday, February 16, 2006
Note that my blog has moved to http://www.pksoftware.net/devblog/.
I stumbled accross NCover Explorer a while ago...
Thursday, February 16, 2006 10:01:08 AM (GMT Standard Time, UTC+00:00) |  | #
Note that my blog has moved to http://www.pksoftware.net/devblog/.
Search
Links
My blog has moved to http://www.pksoftware.net/devblog/
Products
Mini SQL Query
Mini SQL Query is a minimalist SQL query tool for multiple providers (MSSQL, Oracle, OLEDB, MS Access files etc.)

Verse Popper
The "Verse Popper" displays bible verses periodically in the lower right hand corner of your screen.

Blogroll
My blog has moved to http://www.pksoftware.net/devblog/