Let me preface this by saying I'm fairly new to Unit Testing, Mocks, Stubs, Etc...
I've installed Delphi-Mock-Wizard. When I select a unit and "Generate Mock", a new unit is created but it's very basic and not anything what I understand Mocks to be.
unit Unit1;
(** WARNING -
AUTO-GENERATED MOCK! Change this
unit if you want to, but be aware that
any changes you make will be lost if
you regenerate the mock object (for
instance, if the interface changes).
My advice is to create a descendent
class of your auto-generated mock - in
a different unit - and override
things there. That way you get to
keep them.
Also, the auto-generate
code is not yet smart enough to
generate stubs for inherited
interfaces. In that case, change your
mock declaration to inherit from a
mock implementation that implements
the missing interface. This,
unfortunately, is a violation of the
directive above. I'm working on it.
You may also need to manually change
the unit name, above. Another thing
I am working on.
**)
interface
uses
PascalMock,
TestInterfaces;
type
IThingy = interface;
implementation
end.
Looking at the source there seems to be quite a bit commented out. I'm wondering, has anyone gotten this to work?
My IDE is D2010.
Thanks.
The Delphi Mock Wizard is not finished. It's barely even functional. The output you posted in your question looks like the only thing that tool is capable of generating. If you want to use it, you'll have to wait until it matures. Since it was last updated in October 2008, you might have to wait a long, long time.
You'll have to choose a different direction for your mocking needs. Please see an earlier Stack Overflow question for advice:
What is your favorite Delphi mocking library?
Related
I have an F# library with lots of non-public stuff I want to test. Currently all code that is not part of the assembly's public API are marked internal (specifically, it's placed in modules that are marked internal). I use the InternalsVisibleToAttribute to make this code visible to my test assembly. However, in order to get the test assembly to compile, all tests that use internal types in their signature (most of them, since I use FsCheck to auto-generate test inputs) must also be marked internal (this needs to be applied to each function, because internal modules won't be discovered by xunit). Additionally, any types used exclusively for FsCheck generation (e.g. type ValidCustomer = ValidCustomer of Customer where Customer is my internal domain type) also need to be marked internal, and FsCheck seems to get stuck when creating internal types, so the tests don't run.
Is there any way to test internal F# code (from a separate test assembly) without having to mark all tests whose signature depends on internal types as internal? Right now I'm simply leaning towards not making anything internal at all in the original code, but ideally there's a way to have my clean-API cake and eat it too.
I've found that the OO world will generally be very opposed to attempting to test anything internal/private directly.
In the functional world I've seen more of a tendency to just expose public functions not intended for public use so they can be tested. See this comment from Edward Kmett.
When I started writing Haskell I started rethinking the way I used to approach encapsulation and hiding.
...
In general I'm a big fan of exposing all of the salient details, constructors and all for my data types through some kind of .Internal module, even if I want encapsulation and safety in the rest of the API.
...
As a side-effect of that you can then use these newly exposed guts to do nice testing. =)
There's a lot more detail in the original comment, and there is a talk where he discusses this at length but I can't find it now.
You could also give the module a really ugly name like __INTERNAL__ to discourage its use.
The question is related to my previous question:
access violation at address in module ntdll.dll - RtlEnterCriticalSection with TCanvas.Lock
Apparently there is a bug in Delphi's code (see QC 64898: Access violation in FreeDeviceContexts). This bug goes all the way until D2010, AFAIK.
The suggested workaround worked fine so far. Now I have a dilemma.
I don't like the idea of using a private copy of Controls.pas in my project - I'm not sure it is safe. The Controls unit is a very low level unit, and I really feel it's a drastic move, considering that my huge application works fine, except for the mentioned problem. I'm also not sure if/how to rebuild all components/units that rely on the Controls unit in my project.
Is it possible to patch TControlCanvas.CreateHandle(), which uses an internal CanvasList and private members?
NOTE: I will be using the patch for this project only (Delphi 5). I don't mind hard-coding the offsets. AFAIK, patching privates always uses hard-coded offsets, based on the compiler version. I might be able to deal with privates myself (without class helpers), but I have no clue how to handle CanvasList and FreeDeviceContext(), which are declared in the implementation section of the Controls unit.
As discussed in the comments, it is possible to access the private and protected members of classes, even in older versions of Delphi without "class helpers".
However, the problem in this case revolves around the details of a particular method implementation, not just being able to access or modify private member variables. Further, the implementation of a particular method which makes use of an implementation variable in the unit involved. Specifically the CanvasList variable that you have noted.
Even with the benefit of class helpers, there is no simple way to access that implementation variable.
Your current solution is the simplest and safest approach: Using a copy of the entire unit with a modification applied to the specific method required to solve the issue.
Rest assured, this is not an uncommon practise. :)
Your only problem with this approach is to be sure to manage the fact that you are relying on this "privatised" copy of the unit when standing up new development environments or upgrading to new versions of the IDE.
In the case of new development environments, careful project configuration should take care of things (and of course, your modified Controls.pas unit is part of your version controlled project).
In the case of upgrading to newer Delphi versions, you simply have to remember to revisit the modified Controls unit in each new version, updating the private copy in your project and re-applying the modifications you have made as appropriate. In most if not all cases this should be straightforward.
But I Really Want to Access the CanvasList Variable
As I say above, there is no simple way to access the implementation variable used in that unit (which will be necessary if you were to somehow contrive to "patch" the code at runtime, rather than replacing it with a modified copy at compile time).
But that implies that there is a **non-**simple way. And there is.
Like any data in your application, that variable resides at some memory address in your process. It's only the compiler scoping rules which prevent you from addressing it directly in source. There is nothing stopping you figuring out how to find that location at runtime and addressing that memory location via a pointer as you would any other "raw" memory address to which you have access.
I don't have a worked up demonstration of how to do that and strongly recommend that trying to implement such a solution is a waste of time and effort, given that an easier solution exists (copying and modifying the unit).
Apart from anything else, depending upon how reliable the method is for determining the memory location involved, direct access to that memory location could prove potentially vulnerable not only to differences between compiler versions but even to changes arising from compiler settings.
In terms of the end result, it is no better than copying the unit but is certainly far harder and far less reliable.
We’re rewriting a calculation core from scratch in Delphi, and we’re looking for ways to let other people write code against it.
Automation seems a fairly safe way to get this done. One use we’re thinking of is making it available to VBA/Office, and also generating a .NET assembly (based on the Automation object, that's easy).
But the code should still be easy to use from Delphi, since we’ll be writing our (desktop) UI with that.
Now I’ve been looking into creating an Automation server in Delphi, and it looks like quite a hassle to have to design the components in the Type Library wizard, and then generate the base code.
The calculations we’re having to implement are described in official rules and regulations that are still not ratified, and so could still change before we’re done — they very probably will, perhaps quite extensively. Waiting for the final version is not an option.
An alternative way could be to finish the entire object model first, and write a separate Automation server which only describes the top-level object, switch $METHODINFO ON, and use TObjectDispatch to return all the subordinate objects. As I see it, that would entail having to write wrappers to return the objects by IDispatch interface. Since there's over a 100 different classes in there, that doesn’t look like an attractive option.
Edit: TObjectDispatch is smart enough to wrap any objects returned by properties and methods as well; so only the top object(s) would need to be wrapped. Lack of a complete type library does mean only late-binding is possible, however.
Is there an other, easier (read: hassle-free) way to write a COM-accessible object model in Delphi?
You don't have to use the type library designer. You can write or generate (e.g. from RTTI of your Delphi classes) a .ridl file and add it to your Automation library project.
Generating interface description from RTTI is a great idea! After you have your interfaces generated you can generate a delphi unit from them and implementing in your classes. Of course the majority are implemented already since you have generated the interfaces from those classes after all. The late binding resolution can be done after that by hand using RTTI and implementing IDispatch and IDispatchEx in a common baseclass of the scriptable classes.
Do I need to put my Interposer class in
all the form that will the particular class ?
Say I want to re-implement TPanel, I redeclare
it as TPanel = class(ExtCtrls.TPanel) in the unit.
Do I need to do this in all the unit that uses
TPanel ?
Thanks in advance !
You yourself have acknowledged that this is a hack. It's not meant to scale well. It's meant for one-time cases where it's not worth the trouble to "do it right" by writing a bona fide custom control.
You can try putting your new class declaration in a separate unit. Make sure that unit appears on uses clauses after the VCL unit that declares the "real" version of the class. If that doesn't work, then yes, you need to make new declarations in every unit that uses the hack.
Since you're doing this to turn TLabel into TStaticText, you'd probably be better off simply changing your TLabel controls into real TStaticText controls on your forms. (That was the answer the last time you asked about this.) That way, the program you ship will be the same program you tested. Otherwise, you're testing a program with one kind of control and shipping one with another.
If you want to design a new component, you'll have to give it a unique name. Otherwise the form designer and the serialization code won't be able to tell them apart. Call it TRoderickPanel or something. Then just replace all your TPanel objects with TRoderickPanel objects on every form that uses them. (GExperts adds a right-click option that makes this much easier.)
Depending on the functionality you are trying to add, you could consider using a class helper. If what you need cannot be done that way, I'd just bite the bullet and create a new class like Mason said. Replacing it right through your code is not that hard really, given that form files are also stored as text.
If you also have Visual Studio installed, that actually has a "Replace in files" command. On top of that I'm sure Google will be able to help you out with stand-alone tools. And I haven't used GExperts in a while, but I'm almost certain that had a "Replace component" command.
This is a far better solution for the long term. If you can use a class helper for what you need, that may be quicker, simpler and less work.
I would instead use the GExperts wizard to replace components to get the behavior you are wanting. Doing what you are suggesting would require re-registration of the components so that the DFM loading mechanism created the proper components, and if I'm not mistaken, the component registry doesn't allow duplicates so would generate an exception. What your suggesting works well with classes, but not components used on a form.
You can put your interposer class into a Unit and add that unit on the uses clause of all units where your interposer needs to act. Pay attention to add this unit AFTER the unit ExtCtrls on the uses clause, otherwise, it will not work
After years of coding Delphi programs as untestable code in forms and datamodules, including global variables, and the only classes are the forms themselves, containing all the code I need for the form UI itself.
How would I convert the code to a set of classes that do the actual work? would I need to stop using the datasources/datasets and do everything in classes? do I need an ORM?
There's usually zero need for reuse of the code in the forms, so does it make sense to convert the logic to classes?
If I encounter a form (or other class) with too much responsibility, I usualy follow the pattern below:
Define a new class for the logic.
Create a member variable of the new class in the form.
Create the class in the onCreate and free it in the onDestroy of the form.
Move a single piece of logic (for example a variable) to the new class.
Move or create all methods to the new class.
Compile and test.
Continue until all logic is put in the new class.
Try to decouple the logic class from the form class. (You can even work with interfaces if you like).
There are situations where a single class is not enough, so it is no problem to create more classes. And these classes can have other classes to.
With these steps, you can tackle most of these problems.
To start with I can highly recommend reading the book Refactoring by Martin Fowler.
This will give you a real understanding about how best to sensibly approach introducing changes to the existing (non OO) code to improve maintainability.
I would not look at an ORM until you have a clear understanding about what benefits (if any) one would bring to your application.
I have encoured problem like this with one application, I start doing the following:
Define main classes for most general logic in the code.
In each form, move the code that process the business logic inside the events as function / procedures in that form.
Then Move these functions/procedures to those classes as static methods.
Finally make only the needed code inside forms like validation UI, and calls to the classes.
For the global variables try to omit as much as you can, and just pass the values as parameters to the methods.
I used static methods, because it's easier for you to remove the code from events and just call them without requiring to Create/Free object for each operation. The original design was not designed to separate the forms from business logic code.
The final application was not full OO, but it least it was easier to test the methods without requiring interacting with the forms and events like before.
Sometimes you feel if you redesign the application from scratch it will be easier than to made changes to make it real OO design.
Another book I can highly, highly recommend - in my personal opinion even better suited than the "generic" refactoring book by Fowler - is "Working Effectively with Legacy Code" by Michael Feathers. It truly showcases the major bumps you will hit while doing that kind of work. Oh, and: Refactoring legacy code can be quite hard on your psyche. I hope you can handle frustration... I like this quote (don't remember where I got it from): "God was able to create the world in 6 days, just because there wasn't any legacy code". Good luck. ;)
Importing into Modelmaker is my first action when confronted with an existing Delphi project. Modelmaker will assist you in refactoring your code because:
It graphically represents all the classes, methods, variables, etc.
It is very tightly integrated in the Delphi IDE (main menu, popup menu,
separate Modelmaker explorer,
toolbar, keyboard shortcuts). This
integration allows you to quickly
perform the necessary actions without
leaving the IDE
It has a dedicated "refactoring" module allowing you to quickly create, move
and rename classes and variables without
having to worry about changing the
underlying code. Modelmaker will
automagically change names and
references in all units.
The basic functionality of Modelmaker is easy to learn. Modelmaker is like any other good productivity tool - The more you put into it, the more you get out of it.
Modelmaker is not free but easily pays for itself in increased productivity.
I have not found a better tool for refactoring legacy Delphi code. They offer a free trial and some decent tutorial movies.
Give Modelmaker a try and good luck...
After understand what you need to refactory your code, and if you want an OPF/ORM, I suggest Jazz SDK