Making a custom control more testable in TestComplete - delphi

(This might be better in the TestComplete forums, but I thought I'd give it a shot here anyway)
We are looking in to automated testing of our Delphi 2010 application with TestComplete. The main control that our application uses is our own custom control that derives directly from TCustomControl.
(For reference the control is like a digraming tool that display boxes with text in them. These boxes can be selected. the control is completely custom drawn, including the selection).
We are looking in to making this more TestComplete friendly so we can read data out of it (e.g. what data is loaded in to the control, what data is selected)
I should also mention that our application uses an MVC architecture and makes heavy use of interfaces. TestCompletes debug agent can't seem to return any type information about interfaces and thus we can't get any data from them. I suspect this is the root of our problem
I'm considering these two approaches:
Add new properties to the control that will return information about the currently selected box(es). e.g. text in the box, position on screen, hierarchical path, and access them via TestCompletes debug agent.
Look at creating a custom control add on for TestComplete (I'm not even sure you can do this with Delphi controls)
The problem with the first approach is the linker will often elimate properties and functions if they are not being used. We want to use our release build for testing not a debug build.
Does anyone have any advice on this or experience with this type of thing?
Thanks
Edit: I've just read the SDK help and custom control addons can only be created for .net and WPF controls.

You are right about the debug info - you can strip it out from the release build. Thus, you will test a release build and have access to internals at the same time.
A note regarding this situation: "the linker will often elimate properties and functions if they are not being used." You can cheat here to make the linker generate debug info for those funcitons:
Make the funcitons published. The linker does not touch published elements.
Make the funcitons virtual. The linker does not exclude virtual methods.
Call your functions somewhere in your code. To include the call in your code without actually calling anything, you can do something like this:
var t: Boolean;
begin
t := False;
if t = True then
TheFunctionThatNeverExecutes();
...
end;

You should reconsider your decision to use the release build for testing. The reason is that TestComplete needs some magic to make your testing life easier while you don't want this magic be present in the release build. So if you can elaborate on the reasons for not using a debug build for testing, we can try to find a solution to revoke this decision. The result may be that you will have access to all the relevant data of your control if you only reveal all available power of TestComplete.
Now back to the original question: You can overcome the interfaces problem by creating some special classes that wrap those interfaces and thus make the properties available in TestComplete.
Create a small (perhaps invisible) test form where you centralize access to instances of these classes. (Now the release mode link) Only create this form in debug mode so, when carefully designed, you only link in the relevant code when needed for testing.

Related

How to get access to an object between dynamically loaded packages?

I need to know the user name and other data of the logged-in user in a project organized using BPLs. That is, how and where do I need to declare the user object and its creation, and how to get access to that object when a package is loaded at runtime? I don't have enough experience working with packages.
In a regular app, for the programmer there is no difference between using runtime packages or all in a single exe
You can change the project to go with runtime packages or not, and your code won't change at all
That changes when you make a modular app that loads BPL modules on demand, chosing at runtime if a given module will be load, and doing it dynamically (ex. app made with a plugin-architecture in mind), then you need to design your own strategy to handle that
Myself, I work in that second way, and I do have some main modules wich give services to the "plugins", so when they are loaded, they do register themselves with the system: user control, navigation, whatever
There is nothing special to use objects in a package. You just add the unit name where the object is defined to the uses clause of the unit where the object is to be used.
You should really read the documentation on this topic. The you may ask more questions to clarify things you don't understand.

Dynamicly resolving Assemblies without the file name

Yes, I've read the warning label, and I know that dynamically loading assemblies is somewhat discouraged. That said, I have an application that loads assemblies - that's just how it works. It works fine on Windows. Works fine on Windows CE. I need it to "work fine" on Android, even if it takes some massaging.
Basically the app is an engine that loads up plug-in DLLs (we'll call it an Adapter) that meet specific interfaces at run time. Under Windows, it even detects the appearance of a DLL at any point and goes and loads it - I'm fine if that's not going to work under Android.
What I'm having trouble getting working is having the Engine load an Adapter that it knew about at design/compile time but without hard coding the name of that Adapter into the Engine code. I'm fine with adding a reference to the Adapter to get it to not get linked out, but I really, really don't want to have to add in the DLL name every time, as the DLLs change with different deployments, and that would lead to a huge headache.
So I figured that if it's referenced, it would get into the APK, and I could use reflection to load it like this:
var asm = Assembly.Load("TheAdapterName.dll");
Initial tests show that this works for the Adapter if I just hard code in the name, but again, I really, really want to avoid that.
So I thought that maybe I could reflect through the references and extract the name, but oddly, not all references actually show up when I do that. So I do this:
var refs = asm.GetReferencedAssemblies().Select(a => a.Name).ToArray();
And I get back an array of 14 assembly names. But the assembly (asm) has 16 references, one of which is the Adapter plug-in I need to load. The Adapter is definitely there - heck I used Assembly.Load with the full name two lines above and it resolved.
I thought, ok, maybe I can figure out the "path" to the folder from which I'm running, and then look for DLLs there and load that way. Ha. After several hours of trying to figure out a way to get the path that would work under Debug and Release, I came up with nothing but more grey hair.
Sooooo...... any thoughts on how I might get the name of a DLL that I know is in my APK, but that I don't "know" the name of at build time (I'm loading them and looking for interfaces via reflection to detect their "Adapterness").
If those methods aren't working for you, then the only suggestion I can think of is to add a prebuild step which updates either a C# or an Assets file in order to provide the list you need.
Obviously this is extra work, but should be fully automated and is guaranteed to work no matter what platform changes get thrown at you.
As an aside, I also just looked at one of my mvx projects using reflector - it shows the same asm.GetReferencedAssemblies() list as your investigations report - runtime-loaded plugins are not listed. I guess that the GetReferencedAssemblies method is reporting only on assemblies actually used to import Type references at the IL level - so if you reference an assembly in the csproj but don't import any types then it doesn't list them as references in the compiled code.

ActiveX Registration

I'm working on an ActiveX where the same code base should be used to two different ActiveXs, meaning, I have the single solution which is built from several DLLs.
When I build the solution for creating the CAB for ActiveX A, I change the DLLs class IDs to specific ones and when I built it for creating the CAB for the second ActiveX, I changed the class IDs to something else.
I need both ActiveXs to be able to run on the same machine.
Basically, it works fine except for that in certain scenarios where I run different versions of the ActiveXs (ActiveX A is from older code version than ActiveX B) there is un-desired behavior.
It looks like that ActiveX loads some DLLs from ActiveX B (which is from different code version).
Sorry for the long description but last important information, since both ActiveXs come from the same code, I have the same class name which is exposed to the javascript which calls the ActiveX.
In the registry there is total separation in all keys except for the following (NetworkInterface is the exposed class):
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MyActiveX.NetworkInterface\CLSID]
#="{31ED2205-F6AE-4133-AD30-60CA2783ADA6}"
When installing ActiveX I see this entry with the right class ID but when installing the second ActiveX the key is overridden by the second ActiveX.
Is it possible to achieve what I'm trying to achieve?
Is there any way to have the same class registered with different class IDs?
Thanks.
#Lior, You answered your question yourself in this phrase: "to have the same class registered with different class IDs". In fact, we are talking about ProgID's, or programmatic identifiers - MyActiveX.NetworkInterface in your case.
There is just one dedicated registry hive for ProgID's - HKEY_LOCAL_MACHINE\SOFTWARE\Classes\, and if you use a ProgID in your client code to instantiate a component, you can do it only for one ActiveX component. When you create an instance using a ProgID, the corresponding CLSID is determined using that registry hive, and the executable DLL/OCX/EXE which implements that class is used. For the latter case, the corresponding registry hive looks like this:
HKEY_CLASSES_ROOT\Wow6432Node\Clsid{6935DB93-21E8-4ccc-BEB9-9FE3C77A297A}\InProcServer32
The best thing which can be done in this case is to use two different ProgID's for your two ActiveX components. Even if you use the same source code for the main classes, you can use them "as is" in two different projects which are used to compile components with separate ProgID's. It seems, all dev environments (VB6 you're maybe using) allow you to do that.
Some more info about this can be found in this article: http://www.vbaccelerator.com/progid.htm
We had the same issue with our ActiveX components, and our experience tells us that to have different ProgID's is the best choice. Even if you release a next version, change the ProgID. This will allow both versions to coexist in the same OS without any problems, and the developers can upgrade the existing projects step-by-step.
===
As an answer to your question, I have an idea of how you can try to solve your problem if you cannot change ProgID's. As I know, you can activate ActiveX's using directly their CLSID's, and different dev environments use different techniques for that. I do not have your project, but if you use JavaScript, you can try the recipe from this article:
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/08652e9e-7deb-40a3-8c1a-f9becdcbf56e/
In a nutshell, you do not need to create your ActiveX objects using a call like this:
myobject = new ActiveXObject("SAMPLEACTIVEX.sampleActiveXCtrl.1");
You need to put your two ActiveX controls on the page using the OBJECT tag and call the methods of your objects using their names (id's) on the webpage. If you look at an example of the HTML OBJECT tag, you'll see something like this:
As you can see, you can use the specified ID to access the members of the object you exactly need. Many examples of that are already on SO - here is one of them:
javascript: "Object doesn't support this property or method" when ActiveX object called

Using EXE's instead of DLL's as plugins - Ways to "one way, one time" transfer information

tldr; at bottom.
Ok, so once again an interesting problem and I'm looking for a fun and interesting solution.
My current project involves being very modular, meaning the program functionality will be easily changed based on different modules and the program would adapt.
So I started out with the typical route, which is using DLL plugins. Now this is just way to normal, I want to think outside the box a bit.
The modules included in my program are long running campaigns that may take weeks to finish, and there will be many running at a time. So stability is a big issue, so I thought about what Google Chrome does. Processes, not DLLs or threads.
So I have a framework going and I need a way to get some information about each module (which are now EXEs). Now for my DLL framework I was exporting a "Register" function that would fill in some information.
So I thought to myself, hey EXEs can export functions, let's see if that actually works...It doesn't. I did some research into how Windows handles theses things and I don't feel like hacking the PE headers on the fly (but it's the out of the box kind of thinking I'm going for).
I'm planning on using named pipes and CLI parameters to transfer data between the main program and the module exe's. I could use that in a register fashion, but I want to here other peoples thoughts.
tldr: I'm using EXE's instead of DLL's for plugins. Looking for a way to easily export one time information like a exported "Register" function would on a DLL. Thoughts?
You might still consider having the modules written as DLLs with defined entrypoints (e.g., the Register function). Then you write the executable that loads the specified DLL. Your main application would fire off the driver executable and give it a name of a plugin DLL.
That way it is still easy to define and export the set of APIs that must be provided yet still run it as a separate process. The one executable that you write can load the specified DLL and then handle the necessary IPC with the main app.
You could define a protocol via the stdin/stdout, named pipes, sockets, etc.
I have successfully used 'plain' COM for several projects, and objects inheriting from TAutoObject. The bonusses here are IDL; the interopability with .Net, VBA and other non-Delphi things; and the fact that implementors still can choose wether to supply a DLL, an exe, an NT-service, and optionally run hosted over the network (COM+/DCOM). There may be several considerations you should handle about multi-threading and locking, but I found all that I needed to know online.
You can, of course, not use symbols exported by a (running) exe since it is running in another boundary. But, you can load an exe as an image (as you would do with a library) using LoadLibrary(Ex) and then, use the functions exported by the exe. I have tested (just for fun) when debugging PeStudio. See the snapshot below of chrome.exe loaded in the process space of PeStudio.exe using LoadLibrary.

How can I check that Properties linking to components is not "lost"?

I'm using Delphi 2007. Sometimes properties linking to components get lost. This is typically Action properties and lookupdatasets. I have a few times had some emergency bug fixes and sent out a version to customers with a somewhat catastrophic result due to this :-)
Anyone know a way to verify that properties that are supposed to be set really are set, or a way to prevent this from happening?
You can assign such values in code, obviously.
More importantly though, you have to diff every file before committing to sourcecontrol. Always.
Make sure your dfm-files is text, not binary. Then it will be easy to see unwanted changes before check-in/commit.
Diffing everything have stopped a lot of potential blunders for me.
An automatic build and test-system would also give you some confidence in what you deliver.
You've received several good answers about how to detect when this does happen (up voted). But one way to prevent it from happening (sometimes) is to make sure that you have added all of the referenced units to your DPR. If you open a form, for example, which contains components that reference other components on a data module, and that data module has not been added to the DPR/project, you're almost guaranteed to have the IDE remove those references, because it removes references which it cannot determine are valid. If, on the other hand, the data module is in the DPR, then the IDE will be able to find it, and it is less likely to remove the references in the first place
Unfortunately, it still happens from time to time, so you still need to take the precautionary measures detailed in the other answers. But this will make things better, if you don't already do this.
Create dunit test project.
Run test before release.
Sound all bells when test fails.
You want a way to verify if the values are set correctly. Well, you can use unit tests for this. Just initiate a form, compare the properties and done.
Comparing the dfm's is also a good way ofcourse but it does not take into account changes due to changed defaults or changes in the code.
When you add a form, data module or frame to a project, the IDE inserts a little comment "tag" after the unit name in the dpr file. It has been my experience that if for any reason this tag is not present, the IDE is more prone to losing cross-module component references.
I wholeheartedly support the idea of always viewing differences before each commit to version control, if you are using such as thing.
I hate to say this but Source Code Control can help in these situations. Even with an emergency bug fix you should be checking everything into a source code repository (Perforce is my personal favorite). In a small fix you could see by what files have changed whether you have any changes you are not expecting.

Resources