Use Visual Studio Test framework to create tests for your code

While writing software over a period of weeks or months, various components of the software get completed at various times. You’ve tested and you’re satisfied they work, and you move on to develop another feature. Or you might check in the source code and somebody else on your team might break your code accidentally with another checkin. This break might not be discovered for days or months.

Checking in test code for the feature alongside the feature code can help prevent such scenarios. These “unit” tests must be simple to run, easy to develop and maintain, and enable you to test your code well. Running the tests might take a minute, but give you the peace of mind that the change you made didn’t break other features. (Or if they did, they might be intentional feature changes, so the tests can be updated)

Software originates at the developer and passes through various stages, like through testing, building, customer installation, Discovering the bug closer to the developer and the time of development is very valuable: waiting til after the tester or customer gets the application is way too late!

Start VS 2008 (I believe it has to be VS Team Server edition or VS Test edition or something like that: See VS 2008 Team System Test Edition)

From the menus, choose File->New->Project Test Documents->Test Project. If you don’t see the option, you probably don’t have the right version of VS. You can even open your existing VS solution, right click on the solution at the top of the Solution Explorer, then choose Add->New->Project. This way, your test code can be in the same solution as your target code.

You can change the default test language (VB or C#) from Tools->Options->Test Tools->Test Project

From the menus, choose Test->Windows->Test List Editor. I like to have that window dockable: right click on the tab and choose Dockable, then dock it where you like.

Open UnitTest1.vb from the solution explorer and you’ll see this code:

   <TestMethod()> Public Sub TestMethod1()

        ' TODO: Add test logic here

    End Sub

Add some code that does something. In your first example, just use this sample code that creates an instance of Excel and my favorite VFP COM Object "t1.c1"

The code manipulates Excel via VB and indirectly via the Fox server. It validates that setting and retrieving Excel cell values works.

If you don’t have Fox, then you can remove the Fox parts

    <TestMethod()> Public Sub TestMethod1()

        Dim oFox = CreateObject("t1.c1") ' no references needed: use late binding

        Dim y = oFox.MyEval("_vfp.servername")

        System.Diagnostics.Debug.WriteLine("y = " + y)

        Dim oExcel = CreateObject("excel.application") ' no references needed: use late binding

        Dim oxlName = oExcel.name

        System.Diagnostics.Debug.WriteLine("Excel name = " + oxlName + oExcel.version.ToString)

        oExcel.visible = True

        oExcel.workbooks.add()

        oExcel.Cells(1, 1).value = "Hi there!"

        System.Diagnostics.Debug.WriteLine("Excel cell=" + oExcel.Cells(1, 1).value)

        Assert.AreEqual("Hi there!", oExcel.Cells(1, 1).value)

        Const nRows As Integer = 30

        Const nCols As Integer = 10

        Dim nSum(nCols) As Integer ' the sum of the cols

       For i = 2 To nRows

            For j = 1 To nCols

                Dim nVal = i * 100 + j ' "(" + i.ToString + "," + j.ToString + ")"

                nSum(j - 1) += nVal

                If i < nRows / 2 Then ' half the vals are filled directly, other half through Fox

                    oExcel.Cells(i, j).value = nVal

                Else

                    oFox.mydocmd("p2.Cells(" + CStr(i) + "," + CStr(j) + ").value=p3", oExcel, nVal)

                End If

                System.Diagnostics.Debug.WriteLine(nVal)

                Assert.AreEqual(nVal, CInt(oExcel.Cells(i, j).value))

            Next

        Next

        For j = 1 To nCols

            oExcel.Cells(nRows + 1, j).Value = _

                "=Sum(" + Chr(j + 64) + "2:" + Chr(j + 64) + nRows.ToString + ")" '"=SUM(A2:A22)"

            Assert.AreEqual(nSum(j - 1), CInt(oExcel.Cells(nRows + 1, j).value))

        Next

        oExcel.ActiveWorkbook.Close(False)

        oExcel.visible = False

        oExcel.quit()

    End Sub

Notice that the test code looks like normal code, except for the Assert.AreEqual calls. These Assert calls will throw an exception if the values aren’t equal, causing the test to fail.

You can remove the manual test from the project by deleting it from the solution. You can add more tests by just adding more Subs with the “TestMethod()” attribute.

You can run and debug/trace/set breakpoints in the test by hitting F5. Or you can run/debug the tests from the Test List Editor window, in which case you can still run other projects from within the same solution. For example, add the Test project to the same solution as the project under test and you can debug your target project while the tests are still running!

Try inserting this code before the line that closes the workbook:

        For i = 2 To 40

            For j = 1 To 30

                Dim cval = "(" + i.ToString + "," + j.ToString + ")"

                If i < 20 Then

                    cval = "VB " + cval

                    oExcel.Cells(i, j).value = cval

                Else

                    cval = "Fox" + cval

                    oFox.mydocmd("p2.Cells(" + CStr(i) + "," + CStr(j) + ").value=p3", oExcel, cval)

                End If

                System.Diagnostics.Debug.WriteLine(cval)

                Assert.AreEqual(cval, oExcel.Cells(i, j).value)

            Next

        Next

It sets the Excel spreadsheet values via calling Excel directly from the test using late binding,and via calling the Fox server to set the value. The C1 class of T1.C1 has a method MyDoCmd defined like so:

      proc MyDoCmd(cCmd as string,p2 as Variant,p3 as Variant,p4 as Variant,p5 as Variant) ;

      helpstring 'Execute a command|%2'

            &cCmd

The “&” just means it takes the string command passed in and executes it. The parameters are called “p2”, “p3”, which are the passed in as the values oExcel and cval

After the test runs, the Test Results pane will show the results. Double-click on one to see the details. If it failed, the results even show you a call stack with hyperlinks of the failure, so you can just click on a stack entry to be taken to the line of code that failed. The failure could be either in the test code or the target code, but you can debug into the scenario to understand what’s going on.

You can make your test assembly be a Friend assembly (using InternalsVisibleTo) to your target project so that you can create instances of various test target classes in your test project.

See also

How to create the general purpose "T1.c1" server: Blogs get 300 hits per hour: Visual FoxPro can count