vsofttechnologies / dunitx Goto Github PK
View Code? Open in Web Editor NEWDelphi Unit Test Framework
License: Apache License 2.0
Delphi Unit Test Framework
License: Apache License 2.0
TDUnitXTestRunner uses unit names to create test hierarchy and there's no way to change this behavior (please correct me if I'm wrong). Do you plan to add more flexibility to this class?
For instance, DUnit provides TTestSuite class for creating test hierarchy. I don't propose adding some sort of TTestSuite to DUnitX, but I believe DUnitX misses this feature.
It would be nice that test-methods fail if they don't do an assertion-call (maybe changeable with an attribute).
The following test will fail:
procedure TMyTests.TestAreEqualWithDouble6DecimalTolerance;
var
Expected, Given, Tolerance: Double;
begin
Expected := 25.5;
Given := 25.499999;
Tolerance := 0.000001;
Assert.AreEqual(Expected, Given, Tolerance);
end;
Changing the variable declaration to Extended allows it to pass:
procedure TMyTests.TestAreEqualWithExtended6DecimalTolerance;
var
Expected, Given, Tolerance: Extended;
begin
Expected := 25.5;
Given := 25.499999;
Tolerance := 0.000001;
Assert.AreEqual(Expected, Given, Tolerance);
end;
Using Double but changing the values also allows it to pass:
procedure TMyTests.TestAreEqualWithDouble4DecimalTolerance;
var
Expected, Given, Tolerance: Double;
begin
Expected := 25.5;
Given := 25.4999;
Tolerance := 0.0001;
Assert.AreEqual(Expected, Given, Tolerance);
end;
This could be because Math.SameValue is overloaded and uses different resolutions depending on value types. Assert.AreEqual always casts the values as Extended. Number literals work fine.
If the unit is not namespaced (ie, Unit1.pas), then an access violation will occur in BuildFixtures.
Reported by Nick Ring.
I'd like to be able to exclude parameters from fixture.fullname and test.fullname in the console logger (and possibly the XML logger).
I'd also like to be able to show logged errors for failed or errored tests in the test summary.
The question is: Where is the right place to feed in verbosity settings? Should the fullname prop be a function with a verbosity level argument?
The formal parameters that contain the expected and actual values in the various Assert methods are now named "left" and "right".
"expected" and "actual" seems like better names - especially for someone new to the framework.
Why is the following necessary:
initialization
TDUnitX.RegisterTestFixture(TFooTests);
To get my project to recognize test fixtures? Can't that just be determined by examining the objects' attributes in the project?
If you create the following class.
MockTestSourceAttribute = class(CustomTestCaseSourceAttribute)
protected
function GetCaseInfoArray : TestCaseInfoArray; override;
end;
function MockTestSourceAttribute.GetCaseInfoArray: TestCaseInfoArray;
begin
SetLength(result,3);
result[0] := TValue.From(0);
result[1] := TValue.From(1);
result[2] := TValue.From(2);
end;
You are able to still call this on a test method with fewer parameters.
[Test]
[MockTestSource]
procedure DataTest(Value : Integer; Value2 : Integer);
The test should fail as the parameters do not match up. Currently you can get access violations on some runs. Its very inconsistent.
Hello,
I just started TDD with DUnitX. I am very impressed and like it. I have 2 questions:
[TestCase('id=3384','3384,L-00355')]
[TestCase('id=2856','2856,???')]
procedure Test_CorrectNotes(const AValue1 : Integer; _Result: string);
procedure TMyTestObject.Test_CorrectNotes(const AValue1: Integer;
_Result: string);
begin
video := TVideo.Create(conn, AValue1);
Assert.AreEqual(video.Notes, _Result, True, 'Notes');
end;
Unfortunately the text for 2856 (therefore the ???) is big and I do not see how I can handle this. The text with CR and LF which I need to compare is below:
Amazon.de
Mit dem Konzeptalbum Tubular Bells, dessen Musik im Horrorfilm Der Exorzist wirkungsvoll zum Einsatz kam, gelangte Mike Oldfield 1973 zu Weltruhm. Der erste Tonträger des Engländers behauptete wochenlang Position Eins der UK-Charts und verkaufte weltweit über sechzehn Millionen Kopien. Zugleich ebnete die Platte, die Rock und Folk mit Kompositionsmethoden der Minimal Music fusionierte, den Weg für eine neue Stilrichtung, der man später das Etikett "New Age" anheftete. In den Jahren nach diesem Bestseller verblasste Oldfields Starglanz zwar etwas, zwei Dekaden danach glückte ihm jedoch mit Tubular Bells II (1992) und Tubular Bells III (1998) eine phänomenale Rückkehr an die Spitze der Hitparaden.
Die Bühnenfassungen der beiden Alben hat der Musiker für die Nachwelt auf Zelluloid bannen lassen. Tubular Bells II, live im Castle zu Edinburgh mitgeschnitten, erfreut die Fans mit einer esoterisch gefärbten Musik zum Träumen und Abheben. Aus kantablen Gitarrenlinien, sanften Keyboardparts, folkloristischen Chorgesängen und allerlei Space-Sounds fertigt Oldfield hier ein Werk von geradezu sinfonischen Ausmaßen. Tubular Bells III, im verregneten London unter freiem Himmel aufgezeichnet, hält für den Zuschauer daheim ebenfalls ein stimmungsvolles Konzertereignis bereit. Am Bildschirm in der Wohnstube lässt sich miterleben, wie Oldfield und seine Mitstreiter einem riesigen Arsenal elektronischer Tonerzeuger mit viel Gespür für Nuancen schwelgerische Sphärenklänge entlocken. --Harald Kepler
Do you have any recommendation how to deal with this? Thank you in advance for any suggestion
I suggest changing the Assert methods to use is by default, but take a boolean to enable using equality checks if needed.
The same change should be made to all overloaded methods.
class procedure WillRaise(const AMethod : TTestLocalMethod; const exceptionClass : ExceptClass = nil; const msg : string = ''; const Identical:Boolean = False); overload;
The private CheckExceptionClass method needs the same argument.
class procedure Assert.CheckExceptionClass(E: Exception; const exceptionClass: ExceptClass; const Identical: Boolean );
begin
if exceptionClass = nil then
Exit;
if Identical
then begin
if E.ClassType <> exceptionClass then
Fail(Format('Method raised [%s] was expecting [%s]. %s', [E.ClassName, exceptionClass.ClassName, E.message]), ReturnAddress);
end
else begin
if not (E.ClassType is exceptionClass) then
Fail(Format('Method raised [%s] was expecting a descendant of [%s]. %s', [E.ClassName, exceptionClass.ClassName, E.message]), ReturnAddress);
end;
end;
Sorry, I haven't mastered this pull business yet. I'll get there. I made some minor tweaks to AreNotEqual to make it consistent with other assertions
{$IFDEF DELPHI_XE_UP}
//Delphi 2010 compiler bug breaks this
class procedure Assert.AreNotEqual<T>(const left, right: T; const message: string);
var
comparer : IComparer<T>;
leftValue, rightValue : TValue;
sLeft, sRight : string;
begin
comparer := TComparer<T>.Default;
if comparer.Compare(right,left) = 0 then
begin
leftValue := TValue.From<T>(left);
rightValue := TValue.From<T>(right);
Fail(Format('left %s equals right %s %s',[leftValue.ToString, rightValue.ToString, message]), ReturnAddress);
end;
end;
{$ELSE}
class procedure Assert.AreNotEqual(const left, right: Integer; const message: string);
begin
if left = right then
Fail(Format('left %d equals right %d %s' ,[left, right, message]), ReturnAddress);
end;
{$ENDIF}
MaxTime attribute would allow failing a test if it takes longer than the specified time. Useful for detecting major perfomance changes when running tests, ie if you know a test usually takes less than say 2 seconds, then add
[MaxTime(2000)]
If it takes longer than 2 seconds then the test will be marked as a failure.
Regression on issue#96 SetupFixture and TeardownFixture are not called if all tests have [repeattest] attributes on them.
The following code will not have its SetupFixture
and TeardownFixture
called:
type
[TestFixture]
TSpeedTest<T> = class(TObject)
private
Bag1, Bag2: array[0..100000] of T;
public
[SetupFixture]
procedure FixtureSetup; <<--\
[TearDownFixture] |---- Never called
procedure TearDown; <<--/
[Test]
[RepeatTest(5)]
procedure Run_Forest_Run;
end;
The cause of this is this code snippet from DUnitX.FixtureProviderPlugin.pas
.
if method.TryGetAttributeOfType<RepeatTestAttribute>(repeatAttrib) then
begin
if (repeatAttrib.Count = 0) then
begin
ignoredTest := True;
ignoredReason := 'Repeat Set to 0. Test Ignored.';
end
else
if (repeatAttrib.Count > 1) then
begin
repeatCount := repeatAttrib.Count;
currentFixture := fixture.AddChildFixture(fixture.TestClass, Format('%s.%s', [currentFixture.FullName,method.Name]),category);
//setup and teardown might have already been set.. so take them from the parent fixture.
currentFixture.SetSetupTestMethod(fixture.SetupMethodName,fixture.SetupMethod);
currentFixture.SetTearDownTestMethod(fixture.TearDownMethodName,fixture.TearDownMethod);
//don't assign setupfixture or teardown fixture as the parent fixture's methods will still be run.
end;
end;
It should be
if method.TryGetAttributeOfType<RepeatTestAttribute>(repeatAttrib) then
begin
if (repeatAttrib.Count = 0) then
begin
ignoredTest := True;
ignoredReason := 'Repeat Set to 0. Test Ignored.';
end
else
if (repeatAttrib.Count > 1) then
begin
repeatCount := repeatAttrib.Count;
currentFixture := fixture.AddChildFixture(fixture.TestClass, Format('%s.%s', [currentFixture.FullName,method.Name]),category);
//setup and teardown might have already been set.. so take them from the parent fixture.
// currentFixture.SetSetupTestMethod(fixture.SetupMethodName,fixture.SetupMethod);
// currentFixture.SetTearDownTestMethod(fixture.TearDownMethodName,fixture.TearDownMethod);
currentFixture.SetSetupTestMethod(fixture.SetupMethodName,fixture.SetupMethod);
currentFixture.SetTearDownTestMethod(fixture.TearDownMethodName,fixture.TearDownMethod);
currentFixture.SetSetupFixtureMethod(fixture.SetupFixtureMethodName,fixture.SetupFixtureMethod);
currentFixture.SetTearDownFixtureMethod(fixture.TearDownFixtureMethodName,fixture.TearDownFixtureMethod,tearDownFixtureIsDestructor);
//don't assign setupfixture or teardown fixture as the parent fixture's methods will still be run.
end;
end;
I'm not sure what happens if there's a mix of tests with and without [RepeatTest]
on them.
I have
type
[TestFixture]
TTestClass<T:TBase> = class
[Test]
[TestCase('TestBase', 'a param string')]
procedure FirstTest(const Param:String); virtual;
[Test]
[TestCase('TestBase2', '2nd param string')]
procedure SecondTest(const Param:String); virtual;
end
Today I use this approach
type
[TestFixture]
TTestClassChild = class(TTestClass<TChild>)
[Test]
[TestCase('TestChild1', 'yet another param string')]
[TestCase('TestChild2', 'more param string')]
procedure FirstTest(const Param:String); override;
[Test]
[TestCase('TestChild3', 'yet another param string')]
[TestCase('TestChild4', 'more param string')]
procedure SecondTest(const Param:String); override;
end;
and the implementation is simply
procedure TTestClassChild.FirstTest(const Param:String);
begin
Inherited;
end;
procedure TTestClassChild.SecondTest(const Param:String);
begin
Inherited;
end;
which only is annoying scaffolding really, especially considering that TTestClass has dozens of tests that has to be scaffolded again and again for over 200 classes.
Instead I would love to do away with the scaffolding code, and only use attributes:
type
[TestFixture]
TTestClassChild = class(TTestClass<TChild>)
[Test('FirstTest')]
[TestCase('TestChild1', 'yet another param string')]
[TestCase('TestChild2', 'more param string')]
[Test('SecondTest')]
[TestCase('TestChild3', 'yet another param string')]
[TestCase('TestChild4', 'more param string')]
end;
i.e. run the FirstTest and SecondTest methods with a different set of test cases without having to inherit and override the methods and having to write the silly scaffolding
Is it possible (if adding new tricks to DUnitX) to define new tests with only attributes? Can they be associated and enumerated correctly?
I'm having trouble getting this to build. It appears the project file is missing several dependencies (DUnitX.Extensibility.pas, DUnitX.Extensibility.PluginManager.pas, and DUnitX.FixtureProviderPlugin.pas).
After adding these dependencies to the project, I get the following build errors:
[dcc32 Error] DUNitX.Loggers.GUIX.pas(80): E2003 Undeclared identifier: 'ITestFixtureList'
[dcc32 Error] DUNitX.Loggers.GUIX.pas(85): E2005 'ITestFixtureList' is not a type identifier
[dcc32 Error] DUNitX.Loggers.GUIX.pas(141): E2005 'ITestFixtureList' is not a type identifier
[dcc32 Error] DUNitX.Loggers.GUIX.pas(143): E2003 Undeclared identifier: 'ITestFixture'
[dcc32 Error] DUNitX.Loggers.GUIX.pas(144): E2003 Undeclared identifier: 'ITest'
I'd really like to have a look at the GUI. If this is something that is not quite ready for prime time, is it something that is still on the DUnitX roadmap?
Whil working with Stefan Glienkes TestInsight, I noticed that it shows the failure messages twice. Hence I created the following issue: https://bitbucket.org/sglienke/testinsight/issue/48/error-message-is-duplicated-in
An ITestResult can contain two messages, Message and ExceptionMessage.
In TDUnitXTestError.Create, the ExceptionMessage is assembled from AMessage and AThrownException.Message, which, during my tests, have always been identical (but this doesn't prove anything).
Hence
Message = 'Expected 17 bot got 42'
ExceptionMessage = 'Expected 17 but got 24 Expected 17 bot got 42'
ExceptionMessage is the one used by TestInsight, which leads me to the following questions:
If it is possible that AMessage and AThrownException.Message are different, I propose the following change to TDUnitXTestError.Create
TDUnitXTestError.Create(
...
FExceptionMessage := AMessage;
if AMessage <> AThrownException.Message then
FExceptionMessage := FExceptionMessage + AThrownException.Message;
FExceptionAddress := Addrs;
...
end;
Looks like something in the runresults is treating ignored tests as errors?
This test:
procedure TDUnitX_LoggerXMLNUnitTests.OnTestingEnds_Fills_The_End_Of_The_Stream_With_Testing_Result_Info;
contains the following mock setup:
mockResults.Setup.WillReturn(StrToDateTime('28/02/2000 12:34:55 PM')).When.FinishTime;
which fails on my US-based computer, as there is no month '28'. ;-)
Is this file missing? Been removed? Are the DPR files that require this file out of whack?
Or am I just completely lost....?
When a test has RepeatTest attribute, the Setup and Teardown methods are not called.
From what I can tell, when a repeated test is created, a childfixture is added to the current fixture. This child fixture is never assigned the Setup or Teardown methods from the current fixture. I believe if this is added, it will solve the problem.
If this is accepted, then I also think a test (or 2) should be added to the TTestRepeatAttribute in DUnitX.Tests.TestFixture.
The XE7 project contains madExcept units in the dpr (probably added by the madExcept IDE plugin by the last commiter)
Some tests contain references to Delphi.Mocks (is it intended that the project is not self contained?)
Also afaik Delphi Mocks does not work on XE.
On XE tests fail to compile with an AV even before reaching the part where Delphi Mocks is used.
As there was no test project for XE, I used the XE2 one
DUnitX lacks a GUI runner like DUnit's. I plan on working on this next (VCL Only).
I'm reworking command line support at the moment to allow specifying which tests to run etc.
[dcc32 Fatal Error] DUnitX.TestFramework.pas(871): F2084 Internal Error: G9413
It appears to be this bug
http://qc.embarcadero.com/wc/qcmain.aspx?d=111979
I tried the work around, and it compiles, however then the TDUnitX class constructor does not get called. The compiler bug was fixed in XE4.
I was looking at implementing the Repeat attribute.
http://www.nunit.org/index.php?p=repeat&r=2.5
Does anyone have any problems if I implement with same behavior as NUnit?
Or is there another desired behavior?
I believe that [Repeat(0)] would act the same as Ignore with a fixed reason, telling it was ignored because it was repeated zero times.
Hi folks,
Passing floating point numbers within the given TestCase-Attribute fails. I do pass them this way:
[TestCase('Test1', '6, 5.44,0.0001')]
procedure TestFloat(const AGiven: Double; const AExpected: Double; const ATolerance: Double);
DUnitX converts the Arguments as listed:
AGiven = 6
AExpected = 0
ATolerance = 0
After debugging, i found that the following piece of Code (Unit DunitX.Utils) does not work for me (XE6):
function ConvStr2Float
.....
AResult := TValue.FromFloat(ATarget, StrToFloatDef(ASource.AsString, 0));
......
Instead of Returning the correct floating point number, it returns the default (0).
Is there anything I do wrong? Passing TFormatSettings manually (and initializing the Decimalseparator) to StrToFloat() works fine instead.
Kind Regards,
Aleks
Hello,
I have the following issue. in some of my result strings colons are contained. But this makes the test fail. here is the code:
[TestCase('id=2000','2000, 25,95')]
procedure Test_CorrectPrice(const AValue1 : Integer; _Result: string);
procedure TMyTestObject.Test_CorrectPrice(const AValue1: Integer;
_Result: string);
begin
video := TVideo.Create(conn, AValue1);
Assert.AreEqual(video.Price, _Result, True, 'Price');
end;
Unfortuntely the result is as follows:
Failing Tests
Unit14.TMyTestObject.Test_CorrectPrice.id=2000
Message: [25,95] is Not Equal to [ 25] Price
Am I doing something wrong or is there a bug?
I would like to enhance the VCL test runner to bring it up to par with the DUnit version (we are on XE3; have no intention to adopt Firemonkey; and want a GUI runner to run single tests in an ad-hoc environment).
So I would like to throw a TDUnitXTestFixture/TDUnitXTestCase at an ITestRunner. However while TDUnitXTestRunner has some methods that support this, they are not exposed via ITestRunner. Would simply pushing those methods up to the interface suffice, or is there another direction this should go in? Also should the creation of the test context be encapsulated by the implementation of these methods? Am keen to add this and submit a pull request, but want some tips...
if you don't use the Compiler Symbol DELPHI_XE_UP, the result is like using CheckEquals.
Implementation:
unit DUnitX.DUnitCompatibility;
one of them:
procedure TTestCase.CheckNotEquals(expected, actual: int64; msg: string);
begin
{$IFDEF DELPHI_XE_UP}
Assert.AreNotEqual(expected,actual,msg);
{$ELSE}
Assert.IsTrue(expected = actual, msg); // !!! this is wrong !!!
{$ENDIF}
end;
Passing JSON as TestCase data will create humongous test names, which also will mess up the XML in the log.
Possible solutions
See also Issue #59
SSCCE
program DUnitX_JSON_TestCase_Bug;
{$APPTYPE CONSOLE}
uses
SysUtils,
DUnitX.AutoDetect.Console,
DUnitX.Loggers.Console,
DUnitX.Loggers.Xml.NUnit,
DUnitX.TestRunner,
DUnitX.TestFramework;
const
NoSep = '¤';
NewTPack = String(
'{"type":"PSDTPack.TPSDTPack","id":"0","fields":{"ReceptionOrderId":0,"ProductionOrderId":0,"TPackNo":"","ClientApplicationId":0,'
+ '"StoragePositionId":0,"LabeledExpirationDate":0,"LabeledArticleNo":"","BornDate":41756.4940430093,"LockState":1,"TPackStatus":0,'
+ '"TPackType":0,"AccessibleInStorage":0,"CarrierWeight":0,"LabeledWhen":0,"IsEmpty":1,"LastCountedDate":0,"SupplierId":0,'
+ '"SupplersGS1No":"703801","CustomerOrder_NFI":"","CarrierTypeId":0,"DeliveryId":0,"AllocatedDeliveryId":0,'
+ '"AllocatedToManufactOrderId":0},"listitems":[]}'
);
ChangedTPack = String(
'{"type":"PSDTPack.TPSDTPack",'
// + '"id":"0",'
+ '"fields":{"ReceptionOrderId":0,"ProductionOrderId":0,"TPackNo":"","ClientApplicationId":0,'
+ '"StoragePositionId":0,"LabeledExpirationDate":0,"LabeledArticleNo":"","BornDate":41756.4940430093,"LockState":1,"TPackStatus":0,'
+ '"TPackType":0,"AccessibleInStorage":0,"CarrierWeight":0,"LabeledWhen":0,"IsEmpty":1,"LastCountedDate":0,"SupplierId":0,'
+ '"SupplersGS1No":"703801","CustomerOrder_NFI":"","CarrierTypeId":0,"DeliveryId":0,"AllocatedDeliveryId":0,'
+ '"AllocatedToManufactOrderId":0},"listitems":[]}'
);
type
[TestFixture]
TestTPSDTPack= class
public
[Setup]
procedure Setup;
[TearDown]
procedure TearDown;
[Test]
[TestCase('Create', NewTPack, NoSep)]
procedure CreateFromJSON(const aJSON: String);
[Test]
function SaveToDB:Boolean;
[Test]
function ReadFromDb:Boolean;
[Test]
[TestCase('Modify', ChangedTPack, NoSep)]
function ChangeAndSave(const aJSON: String):Boolean;
[Test]
function DeleteFromDb:Boolean;
end;
{ TestTPSDCarrierType }
function TestTPSDTPack.ChangeAndSave(const aJSON: String): Boolean;
begin
Assert.Fail('Something went wrong');
end;
procedure TestTPSDTPack.CreateFromJSON(const aJSON: String);
begin
end;
function TestTPSDTPack.DeleteFromDb: Boolean;
begin
raise Exception.Create('That didn''t go as planned');
end;
function TestTPSDTPack.ReadFromDb: Boolean;
begin
end;
function TestTPSDTPack.SaveToDB: Boolean;
begin
end;
procedure TestTPSDTPack.Setup;
begin
end;
procedure TestTPSDTPack.TearDown;
begin
end;
var
runner : ITestRunner;
results : IRunResults;
logger : ITestLogger;
nunitLogger : ITestLogger;
const
QuietMode: Boolean = False; // False = Detailed test log
begin
try
//Create the runner
runner := TDUnitX.CreateRunner;
runner.UseRTTI := True;
//tell the runner how we will log things
logger := TDUnitXConsoleLogger.Create(QuietMode);
nunitLogger := TDUnitXXMLNUnitFileLogger.Create;
runner.AddLogger(logger);
runner.AddLogger(nunitLogger);
TDUnitX.RegisterTestFixture(TestTPSDTPack);
//Run tests
results := runner.Execute;
{$IFNDEF CI}
//We don't want this happening when running under CI.
System.Write('Done.. press <Enter> key to quit.');
System.Readln;
{$ENDIF}
except
on E: Exception do
System.Writeln(E.ClassName, ': ', E.Message);
end;
end.
I just wanted to achieve something like:
http://softwareonastring.com/2014/11/09/how-do-i-test-an-interface-should-i-even-do-that
I have an interface which is implemented by several objects. My plan was to create a base testclass which contains all the tests and to derive this class for each type which implements the interface. I need to derive the base class cause I need to setup some parameters (different on each type).
As far as I can see, it is not possible in DUnitX to inherit test methods from a base class.
Primary caused by:
procedure TDUnitXFixtureProvider.GenerateTests(const context: IFixtureProviderContext;
const fixture: ITestFixture);
...
//important to use declared here.. otherwise we are looking at TObject as well.
methods := rType.GetDeclaredMethods;
...
Does anyone why it is "important" to use the declared methods here? (instead of using all methods)
Regards,
Jens
Allow tests to be written in C++.
--options or --opt seems to be just silently ignored.
It's planned the support of inheritance in TestFixtures like
http://www.nunit.org/index.php?p=testFixture&r=2.5.5 ?
When setting colors, the console writer assumes the background colour is black.
But on most of my systems it is white, resulting in very hard to read output.
The console writer should either force a black background, or (much harder) choose the foreground colours to contrast nicely with the background colour.
The ASM code prevents DUnitX from supporting other platforms.
Also, the ASM code could just as well call the native Win32 functions defined in Winapi.Windows for newer versions of Delphi.
function InterlockedCompareExchange; external kernel32 name 'InterlockedCompareExchange';
function InterlockedCompareExchange64; external kernel32 name 'InterlockedCompareExchange64';
function InterlockedCompareExchangePointer(var Destination: Pointer; Exchange: Pointer; Comparand: Pointer): Pointer; inline;
begin
Result := Pointer(IntPtr(InterlockedCompareExchange(Integer(IntPtr(Destination)), IntPtr(Exchange), IntPtr(Comparand))));
end;
function InterlockedDecrement; external kernel32 name 'InterlockedDecrement';
function InterlockedExchange; external kernel32 name 'InterlockedExchange';
function InterlockedExchangeAdd(Addend: PInteger; Value: Integer): Integer; external kernel32 name 'InterlockedExchangeAdd';
function InterlockedExchangeAdd(var Addend: Integer; Value: Integer): Integer; external kernel32 name 'InterlockedExchangeAdd';
function InterlockedExchangePointer(var Target: Pointer; Value: Pointer): Pointer;
begin
Result := Pointer(IntPtr(InterlockedExchange(Integer(IntPtr(Target)), IntPtr(Value))));
end;
function InterlockedIncrement; external kernel32 name 'InterlockedIncrement';
I have a zip file of a simple project that shows the problem. There doesn't seem to be a way to attach it to this issue report.
Steps to reproduce.
Exp: Test runs
Act: AV in line 267 of DUnitX.TestRunner.pas
If you add a namespace (i.e., "SomeTests.MyTests.pas") then the project runs fine.
I believe that the error occurs because the code assumes that the "namespaces" variable will have a blank at the beginning, when it does not.
the Code:
{$IFDEF DELPHI_XE_UP}
//if there is a Destructor then we will use it as the fixture
//Teardown method.
if method.IsDestructor and (Length(method.GetParameters) = 0) then
begin
// ******** here comes the error: the Parameters are in wrong order ********
currentFixture.SetTearDownFixtureMethod(TTestMethod(meth),method.Name,true);
tearDownFixtureIsDestructor := true;
tearDownFixtureMethod := TTestMethod(meth);
continue;
end;
{$ENDIF}
There is a prototype of a GUI Logger in the project, do you have the intended in support this type of logger? And why did you use VCL and not Firemonkey ?
Add Category Attribute and apply Fixtures and Tests so we can filter by Category (ie, only run fixtures/tests with specific categories)
TDUnitX.RegisterTestFixture()
It is possible to register 2 TestClasses with the same Name. But only the first registered Class will be executed. You get no Exception, no Message.
In DUnit it is possible and all Tests will be executed!
Testing strings containing " seem to have problems. Example:
[Test]
[TestCase('tomt', 'password="",password=""')]
procedure Test_String(AString, AResult: string);
The procedure Test_String
can have empty implementation. It will succeed, and the output will be like this:
<test-case name="Test_String ( password="", password="" ) [Test_String]" executed="True" result="Success" success="True" time="0.000" asserts="0" />
ContinuaCI doesn't handle this. I don't know if this is an error in output or on error in parsing?
/Anders
Just a question...... why did we decide to use a registration process rather than {$STRONGLINKTYPES ON}?
I often have to write:
assert.Implement<IMyInterface>(myObject)
myObjectAsMyInterface := myObject as IMyInterface
What do you think of chaning the method
procedure Assert.Implement<T>(...)
to
function Assert.Implement<T>(...) :T
?
With this it is possible to write:
myObjectAsMyInterface := assert.Implement<IMyInterface>(myObject)
In the file DUnitX_IDE_Expert_XE.dproj there is small bug. Instead of <DCC_DebugInformation>0</DCC_DebugInformation>
it should be <DCC_DebugInformation>false</DCC_DebugInformation>
.
Sometimes one testmethod implements multiple tests.
It would be nice to have an option to log any failures, but allow the test to run in order to detect any subsequent failures as well.
One option would be to use code like this:
try
Assert.IsTrue(ResultF = ResultS, 'message');
except
LogFailureWithDUnitX('other message');
end;
Can this already be done, if not adding the LogFailure code would be useful.
I have converted a unit from DUnit to DUnitX, and have an old issue - If I include a specific unit (which is large and deeply entangled with the rest of our code), then the registered tests fail to be called. I have isolated down to this specific unit, whilst I can appreciated that this is not enough information to solve it, where can I look to see what is going on? The test fixtures are there, they don't seem to have any tests associated within them.
Just another way of doing it. xUnit does this, there is no Fixture Setup or Teardown attribute.
Currently I am looking at adding parameters for command line. The one in particular I am looking at is:
/Fixture:FixtureA,FixtureB
This would allow the caller to execute certain classes of tests as they require, rather than all tests.
The issue I am experiencing is that TCommandLine is a singleton. Calling this singleton in my test changes the state of the current test runner. The only way around this I can see would be to raise the exposure of the TCommandLine class.
Does anyone see another way around this?
I have been playing around with DUnitX and the IMemoryLeakMonitor and tried to activate FastMM as MemoryLeak-Monitor.
After activating FastMM as IMemoryLeakMonitor, 95% of my testmethods were leaking - which is definitely wrong (neither EurekaLog nor FastMM (with ReportMemoryLeaksOnShutdown) were reporting any leaks after the whole test run before).
So there must be something wrong, but I dont know what ;-) I attached a sample Project here: Click me
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.