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
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.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
oFox.mydocmd("p2.Cells(" + CStr(i) + "," + CStr(j) + ").value=p3", oExcel, nVal)
Assert.AreEqual(nVal, CInt(oExcel.Cells(i, j).value))
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))
oExcel.visible = False
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
cval = "Fox" + cval
oFox.mydocmd("p2.Cells(" + CStr(i) + "," + CStr(j) + ").value=p3", oExcel, cval)
Assert.AreEqual(cval, oExcel.Cells(i, j).value)
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'
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.
How to create the general purpose "T1.c1" server: Blogs get 300 hits per hour: Visual FoxPro can count