With my memory refreshed on WinDev's testing capabilities, I created a test class as follows:
Code Block |
---|
MyClass is class
END
PROCEDURE Constructor()
PROCEDURE Destructor()
PROCEDURE MethodA(intValue is int)
RESULT intValue
PROCEDURE MethodA(strValue is string)
RESULT strValue
PROCEDURE MethodB(value)
RESULT value |
I started with MethodB, which takes a parameter of undefined type.
Here's my test data - the first iteration passes a number, the second a string.
In both cases I get back the expected value, but am I really passing a string? I hadn't put it in quotes. I tried setting a breakpoint in the class, but the break point never triggered.
So I thought I'd do what I often do in Clarion when I can't rely on the debugger: use OutputDebugString. This is a Windows API call that writes a string to the system log, which you can view with the DbgView utility.
But how to call OutputDebugString?
It turns out there's a utility program included with WinDev called WDAPI, and it will write the WinDev code you need for various API calls:
The code I needed was:
Code Block |
---|
lpOutputString is int système // C Type:LPCSTR, is a string address, you can also specify a string directly
API("KERNEL32","OutputDebugStringA",lpOutputString) |
but it would be silly to add that to every method. Much easier to create a global procedure, right?
In the project explorer I found the Procedures node and right-clicked. I got options to create a subfolder and create a global procedure set. The latter seemed like it would get me a little closer; I guess a procedure set is a way of grouping global procedures. But how to create the procedure?
I found that option on the main menu under Insert. But nothing happened when I exercised that menu option. I was still in the procedure set with no procedure.
So I closed the procedure set without saving and then I tried again, this time without creating the procedure set first. I got a window to save a new procedure set:
and then a prompt asking me for the name of my procedure, which I called Debug. When I saved I got the procedure declaration, and I pasted in the code from WDAPI:
As you can see I had a syntax error, which I wasn't sure how to handle.
But first I updated my MethodB code to call Debug():
Code Block |
---|
PROCEDURE MethodB(value)
Debug(value)
RESULT value |
The help seemed to indicate that I could specify a string directly instead of using the suspect definition for a long pointer. That didn't seem right to me, first because sMsg is a WinDev string and second because the API call really is expecting a pointer. But what the heck - maybe WinDev was working some magic with the API call. So I tried:
Code Block |
---|
PROCEDURE Debug(sMsg is string)
// lpOutputString is int système // C Type:LPCSTR, is a string address, you can also specify a string directly
API("KERNEL32","OutputDebugStringA",sMsg) |
but that crashed the test. So I declared the pointer this way:
nLpOutputString is system int
and then I dug around until I discovered that the address operator is the ampersand. So I assigned the string address
nLpOutputString = &sMsg
which compiled fine. When I ran the test, however, I got a runtime error on the API call and the test failed.
Clearly I needed to find a way to change my string to a cstring and feed the cstring pointer to the API call.
Eventually I came across a page that indicated I needed to use the ASCIIZ string type in this situation. Only one problem: there is no ASCIIZ string type in WinDev 17, at least not that I can see. But there is an ANSI string type.
Here's the code I ended up using:
Code Block |
---|
PROCEDURE Debug(sMsg is string)
nLpOutputString is system int// C Type:LPCSTR, is a string address, you can also specify a string directly
sDebugMsg is ANSI string
sDebugMsg = sMsg
nLpOutputString = &sDebugMsg
API("KERNEL32","OutputDebugStringA",nLpOutputString) |
Now my unit test ran, and more importantly I could see the log statements in DbgView's window.
Code Block |
---|
[4520] abc
[4520] 35 |
And I was out of time. More tomorrow!