What's the easiest way to access other .exe data in delphi? - delphi

I trying to implement some basic automated testing on a 10 million LOC project that don't follow good OO pratices (ex: isolating business logic into classes/units) with the DUnit that comes along with Delphi 2010. I can't do normal unit testing on this project since each part of business logic is spread across a dozens of interdependent units, these 'groups' of units are, however, centered around certain 'main business logic screens' (ex: all invoice logic related units are centered on the main invoice screen), and since those screens are classes I can do 'main business logic screen class testing' instead of unit testing, but those 'main screens' still need a lot of stuff that is created during the process startup.
So I need to both:
Be able to run the bad project's startup stuff
Be able to access its objects
The bad project already have some exported functions that return pointers that I can cast to access it's objects, but I'm unable to call them either way:
If I create the bad project as a child process of the test process, the startup code run fine, but I can't find a way to call the exported functions without complex IPC methods or substantial change on the bad project's structure.
If I load the bad project's .exe as an dll as with the LoadLibrary function, calling any function exported by bad project's result in access violation and/or segfault errors, even this simple procedure:
procedure Test; {safecall;} {stdcall;}
begin
showmessage('Yay!');
end;
How can I do both?

The approach you're talking about (using exported functions) is not going to fly. The simplest form of communication between two Win32 programs is to have them use SendMessage or PostMessage to talk to each other. Locating the window handle (usually by window class name) is step 1, sending a message is step 2.
Secondly, DUnit gets you nowhere near your goal, and TTestCase cannot be extended neatly to be a GUI Controller as that's not what it's for. It's for unit testing. Round peg, square hole. Write TTestCases for classes you can hive off and test, and use DUnit to provide test coverage for those parts of your system that you can provide test coverage for.
For UI testing, use a completely separate framework. There are two basic approaches done by Delphi programmers for automated integration tests of the sort you're proposing.
A custom hack job. Such is what you are describing. Inside Embarcadero, there exists a framework which is called Zombie, something Nick blogged about back in 2007. Its approach is based on several kinds of "primitive IPC", usually involving a Win32 SendMessage or PostMessage window message from outside the program to a window handle of a control inside the program. However, the internal code IS SIGNIFICANTLY MODIFIED to permit zombie testing. No you can't have Teh Codez, they're internal and proprietary to Embarcadero. But it does illustrate that the approach does work, and does not require rewriting the whole application or writing a huge number of mock-classes, like unit testing
would have done. If you want to go down the hack route, you will be writing your own User Interface Testing Framework, which should probably be completely separate from and use no DUnit code. You are welcome to try, but I'm telling you, it's a serious impedance mismatch. If I was starting my own custom framework in 2013, it would be DCOM based, because Delphi DCOM server code could be simply conditionally compiled into many programs, and DCOM would handle the function call "marshalling" details for you. I suspect I would get a year into the project, and I would give up, because in the end, I doubt I could make any system (DCOM or Win32 message based) pay off.
A complete external testing tool which you write test scripts in, like AutomatedQA/SmartBear TestComplete. Your tests would not be compiled into a delphi test program, but run inside TestComplete, and Pascal-like script syntax is just one of the available options for writing your test scripts.

We have had the same problem here. It looks like you really need a delphi library project (*.dll) for the export functions to work, (I suspect no initalization of the framework takes place when calling the function directly on an executable, no warranties).
NOTE: We are still using Delphi 5, so no dunit intergration here.
The solution we've used is to adding the dunit sources to our project (the .exe project) with a conditional DEFINE, and use this conditional define in the startup unit.
Sample startup code from our application:
if ComServer.StartMode <> smAutomation then
begin
OurApplication.Login ;
end;
{$IFDEF _AS_TESTRUNNER_}
GUITestRunner.RunRegisteredTests;
{$ELSE}
if OurApplication.HasStartCommands then
begin
Application.ShowMainForm := False ;
end
else begin
if ComServer.StartMode = smAutomation then
Application.ShowMainForm := False
end;
Application.Run;
{$ENDIF}
OurApplication.Finalize;
When I use the _AS_TESTRUNNER_ conditional define, I must login first so our app (and db connections) get initialised. Followed bij the GUITestrunner of DUnit.
Testcases can be registered in the initialization part exactly as in the examples.
Works like a charm.

Related

How do I access unsupported UI elements?

I want to test a Delphi application with Coded UI Tests, but I have some problems. I want access to some elements in the UI but cannot access all elements.
There is a list on the screen with some rows (according to the search parameters) and I want to access these rows to check the consistency of the values. But with the cross of Coded UI Test Builder I cannot access the rows on the application. How do I access the rows?
I just found one solution for now: Develop an extension for Coded UI Tests to interact properly with my Delphi application like the sample on the Microsoft Web site. It's an extension for Excel that allow you to access each cell. But it sounds difficult and the application I have to test is really complex as well.
If your interface is plain VCL, you can access most components by using their underneath HWND handle. It will work for TEdit TMemo TComboBox TCheckBox and so one. But some graphics components won't be able to be accessible from GDI messages, e.g. TLabel or TGrid.
So I guess you'll have to use a Delphi plug-in in your application, to let accessible the VCL components level. Use the ComponentCount + Components[] properties of a TForm (via recursive call) to access your component to be tested. Then publish its properties to the Coded UI Tests extension, which is to be written.
I speak about a "plug-in" here, because I do not think we may easily have access to all classes to be monitored / modified. Some "plug-in" architecture may help an application to work as usual, or in "Coded UI Tests mode", during testing phase. Perhaps better that a separated compilation for the purpose of tests: you should better test the final compiled executable. If you want only unit testing, you may recompile, stub and mock your application to only test a given form. But you'll need to code the form to be easily unit-tested (using dependency injection or such), which is far from easy in the default Delphi world (as with other RAD approaches).
Could be interesting to initiate an Open Source project (included with DUnit?) to develop such a platform. Or use an existing UI test framework for Delphi as base. A lot of companies we work in are mixing .Net and Delphi technologies, and would benefit for such a tool.

Unit testing a Firemonkey Application

I'm trying to use DUnit, which came with RAD Studio XE2, to unit testing a Firemonkey app (C++).
The problem is, DUnit is a VCL project, and this makes me unable to include the Firemonkey Unit Forms (ex.: UfrmMain.h) on the testing project.
Even if I separate the Visual with Logic (MultiTier/MVC), i cannot include any Firemonkey library into my classes (sometimes this would be useful, when there is a class "CustomDatabase" which have a object of type TConnection, that is only available in Firemonkey - of course only an example).
The testing is possible when i separate the firemonkey code completely and leave it on forms, and the logic/data kept on classes with pure C++ code.
So, this "handicap" is actually a good thing? Forcing me to work with MultiTier/MVC? (This thing in C++ is new to me)
Or should i look for an alternative of unit testing, that lets me test forms too?
(Can you also recommend me some C++ project on github or code example which is separated in the mentioned way, where i can rely on?)
One possible approach would be to use TextTestRunner rather than GUITestRunner. I've never actually tried this but I think it quite plausible that TextTestRunner does not use any VCL units, or at the very least what it does use can easily be excised. And indeed a quick scan of the source code suggests that this will work.

External modules implementation

What is the best way to implement an external module system for a DELPHI application?
What I need is very basic really:
The main APP detects if a module is present and loads it(Run time)
Modules can store form
Modules can store DataModules
Modules can Store code
I need the use the store forms inside other forms, and only as a standAlone
I use something like this
if Assigned(pNewClass) then begin
Application.CreateForm(pNewClass, _lFrm);
_lFrm.Hide;
_lFrm.BorderStyle := bsNone;
_lFrm.Parent := pBasePNL //(TPanel);
_lFrm.Align := alClient;
end;
So I create a TForm, but place it inside a TPanel.
As for DataModules I usally store ImageLists so the ideia is to change the app ICOs just bit changing the external module.
So what is the best way to achieve this?
Looked at runtime BPLs but don’t seem to understand how to do it.
Thanks.
UPDATE : .....................................
After reading some related question and answers i think I found my answer and solution.
http://edn.embarcadero.com/article/27178
The article is old stuff but amazingly simple.
Well the logic is there I just don’t seem to get it to Show the forms 
I am just testing example 2
It loads the BPL, but doesn’t get the Form:
AClass := GetClass('TForm2');
Always retrievex ‘nil’
But the BPL as it registered:
RegisterClass(TForm2);
Can anyone help with this one.
Packages are an easy solution but they have one huge drawback. Using packages forces plugin authors to use not only Delphi, but the same version of the compiler as you do.
I personally would prefer to expose the functionality of the app through a number of interfaces. This allows accessibility from languages other than Delphi.
Typically the plugin would be implemented in a DLL and would export a function that the app would call to pass in the root interface representing the app. The plugin would then call methods of that interface thus establishing two-way interaction.
I made you a demo, it's so easy to get started! However... Started is not finished.
Every time I started using plugins, I later regretted it. However, as you say, you want a binary plugin system. So BPLs are the correct solution. David suggests using interfaces (with plain DLLs instead of the full runtime package BPL) and this would solve some of the commonly encountered BPL-instability problems due to not versioning your classes, and thus your Application-and-package-binary-compatibility dependencies, properly. If you do not need to share memory and do not need to use borlandmm.dll (shared memory management) then a straight DLL with interfaces will work fine.
If you can do everything you need to do with just scripting, and make your plugin system with just scripts, then do it that way. If you can get away with DLLs, interfaces, and no memory sharing, then use plain DLLs. If you must share Memory and class types, then yes, use BPLs.
Beware that using BPLs (Runtime Packages) comes with a lot of side effects you might not have been expecting. The largest BPL-based applications I have worked on have been more of a mess, and less stable, than any monolithic apps I have worked on. It seems that it is only possible to pine for packages until you try them, and then I find, I pine for monoliths again.
If you use BPL packages correctly, and you version your plugins properly, everything is fine. BPLs are great. But in the real world, it seems that sane versioning and ABI compatibility and interoperability, and stability are at a premium.
Update: I made you a demo it's here (plugin_r2.zip). It was done in Delphi XE, but if you are using an older version of delphi, you just delete the .dproj files and open the .dpr file for the main app, and the .dpk for the package.

Using DUnit from the Delphi IDE and avoid breakpoint on exceptions

I'm using Delphi XE and I've got a project group containing the main application and a DUnit test application. From time to time, I go to the DUnit test application to add some tests and run existing one.
Some test code generates exceptions which are handled by the application, but displayed multiple time by the Delphi Debugger as I'm used to running the test application using the F9 shortcut like I do with standard application: this is not very handy in that case.
I know about the SHIFT+CTRL+F9 shortcut to run without debugging and that's great when I remember to use it but I often find myself hitting F9, then grunting, then closing the test application, then hitting SHIFT+CTRL+F9. What a lost of time.
So my question: is there a better way ? Can I define some settings or use some expert to make that particular application run without debugging by default ? Surely I'm not the only one having this issue.
Thanks in advance.
Nope (at least not up until D2009). Run without debugging is an IDE thing. A comiler flag would not help as it is the IDE that hooks the exe, not the other way around. The only place where you could have such an option would be in the project settings. But having it could make the IDE slightly confusing as the normal distinction between Run and Run without debugging would be overruled. You would then need a third option I guess, "Run", "Run with debugging" and "Run without debugging" where the simple "Run" would take its cue from the project options.
Disable "notify on language exceptions".
Add the run-without-debugging icon to the toolbar. Your problem is you forget the hotkey, and click the icon. So remove the other icon, or move them both around, like this:
The bigger your application grows, I find, the slower the debugger startup gets. I run without debugging about 99% of the time now, because the startup time of my app goes from 2 seconds, to 2 minutes, because it uses a lot of runtime packages, and every BPL load in the debugger comes at a huge hit to my productivity. So long, slow painful experience has re-educated me to ask myself "Do I really need to debug?". If I don't, I click the nice green icon (in XE) that replaces the exclamation mark icon in older versions. (A smart UI improvement I think.). In previous delphi versions, the green play button meant "run with debugging".
Well kind of. You can use non-breaking breakpoints[McKeeth][Jensen] to ignore the exceptions you are forcing in your tests. The only way to save breakpoints I know of is to enable Tools > Options > Autosave > Project desktop.
I understand your problem, but personally I don't think it's that useful having an option to change the default behaviour of F9.
You have some test cases which are expected to raise exceptions. (NOTE: I'm actually thinking tests that check for particular exceptions when bad inputs are given. Not exceptions being 'handled' by application.) And I agree there is no point in being alerted to these in most circumstances. However, an exception in other test cases would be a problem that I'd like to be alerted to as quickly as possible.
So my preferred running mode is to usually be notified of exceptions. And have explicit code in certain test cases that explicitly disables exception notification only within the context of the tests that will trigger production code exceptions.
I have a technique that works very well for this.
In a test that's expected to raise exceptions I write the following code:
begin
TIDEDebugTools.DisableBreakOnExceptions;
try
//Test code ...
finally
TIDEDebugTools.EnableBreakOnExceptions;
end;
end;
I guess you want the source code for those 2 methods? :)
unit IDEDebugTools;
interface
type
TIDEDebugTools = class(TObject)
public
class procedure DisableBreakOnExceptions;
class procedure EnableBreakOnExceptions;
end;
implementation
{ TIDEDebugTools }
class procedure TIDEDebugTools.DisableBreakOnExceptions;
begin
end;
class procedure TIDEDebugTools.EnableBreakOnExceptions;
begin
end;
end.
Where's the rest you ask?
There isn't any - that's it!
... but there are a few instructions you need to follow:
Add a breakpoint to each of the method.
Edit the breakpoint-properties.
Select advanced options.
Turn off the "Break" option
And turn on the "Ignore subsequent exceptions" and "Handle subsequent exceptions" options for the appropriate respective method.
This is close to jpfollenius' idea for compiler directive options. It also addresses David's concern about how you enable those exceptions again. All you need to do is disable the breakpoints to get all exceptions reported again.
Additional thoughts:
You mention:
Some test code generates exceptions which are handled by the application.
If your application is handling all these exceptions, then:
Are your tests localised enough? If you're testing such large chunks of functionality, the tests are more like system tests - and can be very difficult to maintain.
Are you making too much use of exceptions for main-line business processing?
Is your application doing a whole lot of inappropriate exception swallowing?
Basically it seems fishy to me that your wording suggested "a bunch of exceptions you're not too concerned about because they're 'handled'". Many people make the mistake of thinking they're handling a exceptions when really they're just swallowing them and hiding the root problems.

Virtual Library Interfaces for Delphi/Win32?

I read this article and find the concept of Virtual Library Interfaces nice for runtime loading of DLLs. However it seems that they aren't available for Win32. Is this true? And if so: Why? I don't see what would tie the idea to .NET.
EDIT: I'm mostly rephrasing here what Rob already wrote. :-)
I'm not after plugins or similar - it's about plain old Win32 DLLs. What appeals to me is the idea to let the compiler deal with all the details of loading a DLL at runtime - no need to call GetProcAddress for every function in the DLL etc.
It seems to me like the three answers so far have completely missed the point of your question. That, or I have. You're asking why Win32 Delphi doesn't have something like the magical Supports function that Hallvard's article talks about, aren't you? Namely, a function that, given the name of a DLL and the type information of an interface, returns an object that implements that interface using the standalone functions exported from the DLL.
Hydra seems to be all about calling .Net code from a Win32 program, not about importing functions from a DLL. TJvPluginManager requires that the plug-in DLLs export a special self-registration function that the manager will call when it loads the DLL, and the function must return an instance of the TJvPlugin class, so the plug-in DLL must be written in Delphi or C++ Builder. The Supports function, on the other hand, works with any DLL written in any language. You could use it on kernel32, if you wanted.
I don't know why Win32 Delphi doesn't have such a thing. Maybe CodeGear didn't see much demand for it since Delphi and Turbo Pascal had already gone for so long without it.
It's certainly possible to write a function that works like that, and I don't expect it would be any harder to write than the .Net version must have been, unless Microsoft's .Net libraries already provide most of the pieces and Delphi just wraps them up into a convenient-to-call function that looks like the several other overloaded versions of Supports that Delphi has had for years.
There would be a few steps to implementing that function in Win32. (I'm providing only a sketch of what's necessary because I don't have a running copy of Delphi handy right now. Ask nicely, and maybe I'll find more details.) First, you'd need to make sure that type information for an interface held, at a minimum, the undecorated names of its methods. Then, Supports would need to generate a function stub for each method in the interface (besides _AddRef, _Release, and QueryInterface). The stub would go something like this, assuming the calling convention is stdcall:
asm
// Pop the return address,
// discard the "this" pointer,
// and restore the return address
pop eax
pop ecx
push eax
jmp AddressOfFunction
end;
As Supports generated each stub, it would fill in the actual function address, gotten from calling GetProcAddress with the name of the corresponding interface method. The stdcall calling convention is easy to wrap like that; cdecl is a little cumbersome; register is a pain in the neck.
Once it has all the stubs generated, it would need to generate an "object" that looks like it implements the given interface. It doesn't have to be an actual class. At compile time, Supports doesn't know the layout of the interface it's going to be asked to implement, so having a class wouldn't accomplish much.
The final step is to provide implementations of the _AddRef, _Release, and QueryInterface. _AddRef would be unremarkable; _Release is where you'd call FreeLibrary when the reference count reached zero; QueryInterface wouldn't do much at all, except claim that it supports IUnknown and the interface given to Supports.
Delphi used to come with a sample program that demonstrated implementing an interface without any classes at all. It was all done with records and function pointers (which is all an interface ultimately is, after all). Delphi also came with the corresponding code to do it with classes, in part to show how much easier Delphi can make things. I can't find the name of the demo program now, but I'm sure it's still around somewhere.
There are a number of Win32 options for this type of functionality. Project JEDI has an open source plugin system as part of the JVCL that loads either DLLs or packages, and can include forms and whatnot as additional functionality.
There are also a number of commercial products available, including the TMS Plugin Framework and RemObjects Hydra.
This is nothing new or special. The article's just talking about plugins. Native code's been able to do plugins for years. The only special thing about P/Invoke is that it allows native code and .NET to talk to each other in a plugin system, and the little trick where "the DLL can be seen as a singleton object that implements the interface [so that] you can use the Supports function from the Borland.Delphi.Win32 unit to check if the DLL and all the methods are available."
If you want to do what the article's talking about in Delphi for Win32, look at the LoadLibrary, GetProcAddress and FreeLibrary Windows API functions. If you absolutely must have an interface like the article describes, you have to write it yourself, either in the DLL (if you wrote the DLL yourself) by writing an exported function that returns an interface, or in the calling app, by writing a function that uses GetProcAddress to create an interface dynamically. (Caution: this requires mucking around with pointers, and is usually more trouble than it's worth.)
Your best bet is probably just to do what Tim Sullivan mentioned: use TJvPluginManager from the JEDI VCL if you only need native code, or Hydra if you have to talk to .NET assemblies.
I've used Hydra myself for a Delphi only solution (i.e., didn't interface to .NET) and it works great for that too. It's easier to use and adds some niceties, but I think that it's basically implemented the same way as the "roll-your-own" plugin framework that is well-described in this article:
http://www.saxon.co.uk/SinglePkg/
I would look for a plugin framework that's interface-based (like Hydra and the "roll-your-own" system in above paragraph), rather than one that simply sends messages between apps.
There is a Delphi plugin framework on sourceforge, don't know whether it's the same one as in JEDI project or not: http://sourceforge.net/projects/rd-dpf
There are also a couple of other commercial solutions, one of which is Dragonsoft's:
http://www.dragonsoft.us/products_dsps.php
What is wrong with doing this with simple com objects? Declare a simple interface that all of your plugins implement, and require that each com object include an exported function that returns its class guid. Then using the "plugins" is as simple as walking thru the plugins directory looking for DLL's which expose the special registration function, invoking it and then using the class guid to then invoke the com object.
I used something like this in a WIN32 commercial application with great success. The advantage was I could switch plugins in and out at will (provided of course the application wasn't running to remove existing ones), the magic was all in the interface that each one implemented.

Resources