Help with Unit Testing in Exercises

Hello:

I’ve made it through two of the exercises and am just starting the third. In each case, there’s been an issue with the Unit Testing that’s included as part of the exercise. For the first two, I just ripped out that code from the basic structure that was provided, but I hate to keep doing that. In this case, I’m looking at the “Twofer” exercise. When I open the project file I get the following errors: F2063 Could not compile used unit ‘utwofer.pas’ at line 15 (15:23) and E2212 Package unit ‘utwofer’ cannot appear in contains or uses clasues at line 15. Line 15 reads: utwofer in ‘utwofer.pas’;

When I last left off doing major programming projects (now about 15-20 years ago) unit testing didn’t even exist, or at least I’d never heard of it. I know now it’s important so I hate to keep ripping it out, but I’m also just trying to get the basics going.

Thanks.

Hey, Doc!

Are you following the instructions that were delivered in the HELP.md file?

Show your code, complete with file names, so that we know we are looking at the same thing.

However, if you are working locally, you can submit a failing exercise and request mentoring, and one of the mentors will likely pick it up and will be able to help you in context of the exercise.

This will also allow us to see exactly what you have, as we will download what you have submitted.

The Delphi track provides empty exercise stub files, which I think is the issue here. The tracks I’m experienced with tend to also provide the necessary function signatures in the stub so the student can focus on the implementation details. There are pros and cons to both approaches, but personally, I’d get frustrated after a while and copy and paste what I need into each exercise. At that point, it’d be a better experience for me if Delphi provides non-empty stubs.

Hi there - sorry for the delayed response. So below is my code - which does seem to work. What I’m trying to do is figure out how to run unit tests. The Readme.md file says:

“Welcome to Gigasecond on Exercism’s Delphi Pascal Track. If you need help running the tests or submitting your code, check out HELP.md.”

So I opened the Help.md file and it says:

Running the tests
In order to run the tests for this track, you will need to install DUnitX. Please see the installation instructions for more information.

So I checked and DUnitX seems to be installed. When I try to run the unit tests It’s looking to compile a pascal source file named uGigaSecond.pas, which I assume is where it wanted me to put the source code. The problem appears to be that when I go to save my Source file, it ONLY gives me the option to save as a Delphi Project (*.dproj). It doesn’t give me the option to save as *.pas file. I think if I could do that (and used the correct file name in the unit test) the unit test would run. But I can’t figure out in the Delphi development environment how to save my file as *.pas.

Thanks!


program ComputeGigaSecond;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils;

const

GigaSecond=1000000000;
Millisecond=1000;

var

StartTime:tDateTime;
TestDateTime:tDateTime;
StartTimeStr:String;

begin
Writeln('Enter Date to add a GigaSecond to ');

Readln(StartTimeStr);
StartTime := StrToDateTime(StartTimeStr);

TestDateTime:= StartTime+(GigaSecond / 86400);
Writeln('Input Date: '+ DateTimeToStr(StartTime));
Writeln('A GigaSecond Later would be: ’ + DateTimeToStr(TestDateTime));

end.


Update: OK, I figured out how to save a file as *.pas. You just type the extension (doh). I thought I had something misconfigured since *.pas wasn’t coming up as a file type. So now the uGigaasecondTests will compile. But nothing happens. It just prompts me for the date (which is what I had the code do) and then returns the result and goes away. How do I run the tests? Or know that the tests have been run? Sorry - I’m sure these are basic questions - but I last wrote in Turbo Pascal so the whole environment is completely different.

Are you running the test suite Exercism provided in uGigasecondTests.pas? If so , you should have a log file for the DUnitX test run in that folder.

To be sure, basic questions are good. If they are not answered in a way that gets students up and running and they are unanswered, then that is not a good thing.

So, we should figure out if it is something that was missed, but is there, or something that was not there but should be.

Here’s a list of all of the files in the directory after I have run uGigasecondTests. I don’t see anything that looks like a log file.

In looking at the uGigasecondTets.pas it kinda looks like my program should be accepting an input parameter when I execute it from the command line - which wasn’t in the instructions. Mine prompts the user for the date, then does an echo print and lists the Gigasecond later value. Is that what it’s looking for?

01/20/2025 07:19 AM .
01/14/2025 06:45 AM …
01/11/2025 01:36 PM .exercism
01/18/2025 04:45 PM 572 ComputeGigaSecond.dpr
01/20/2025 07:18 AM 75,125 ComputeGigaSecond.dproj
01/20/2025 07:18 AM 318 ComputeGigaSecond.dproj.local
01/18/2025 04:52 PM 95 ComputeGigaSecond.identcache
01/20/2025 07:18 AM 75,125 ComputeGigaSecond.pas
01/20/2025 07:18 AM 534 ComputeGigaSecond.pas.local
01/20/2025 07:19 AM 96 ComputeGigaSecond.res
01/11/2025 01:36 PM 1,572 HELP.md
01/11/2025 01:36 PM 2,188 README.md
01/11/2025 01:36 PM 0 uGigasecond.pas
01/18/2025 05:01 PM 1,469 uGigasecondTests.pas
01/12/2025 07:17 AM Win32
11 File(s) 157,094 bytes
4 Dir(s) 288,061,530,112 bytes free

Also - in case someone doesn’t have access to it, here’s the uGigasecondTests.pas code:

unit uGigasecondTests;

interface
uses
DUnitX.TestFramework;

const
CanonicalVersion = ‘2.0.0.1’;

type
[TestFixture]
TGigasecondTest = class(TObject)
public
[Test]
// [Ignore(‘Comment the “[Ignore]” statement to run the test’)]
procedure date_only_specification_of_time;

[Test]
[Ignore]
procedure second_test_for_date_only_specification_of_time;

[Test]
[Ignore]
procedure third_test_for_date_only_specification_of_time;

[Test]
[Ignore]
procedure full_time_specified;

[Test]
[Ignore]
procedure full_time_with_day_roll_over;

end;

implementation
uses
ComputeGigaSecond;

procedure TGigasecondTest.date_only_specification_of_time;
begin
Assert.AreEqual(‘2043-01-01T01:46:40’ ,TGigasecond.Add(‘2011-04-25’));
end;

procedure TGigasecondTest.full_time_specified;
begin
Assert.AreEqual(‘2046-10-02T23:46:40’ ,TGigasecond.Add(‘2015-01-24T22:00:00’));
end;

procedure TGigasecondTest.full_time_with_day_roll_over;
begin
Assert.AreEqual(‘2046-10-03T01:46:39’ ,TGigasecond.Add(‘2015-01-24T23:59:59’));
end;

procedure TGigasecondTest.second_test_for_date_only_specification_of_time;
begin
Assert.AreEqual(‘2009-02-19T01:46:40’ ,TGigasecond.Add(‘1977-06-13’));
end;

procedure TGigasecondTest.third_test_for_date_only_specification_of_time;
begin
Assert.AreEqual(‘1991-03-27T01:46:40’ ,TGigasecond.Add(‘1959-07-19’));
end;

initialization
TDUnitX.RegisterTestFixture(TGigasecondTest);
end.

Not quite. The test suite contains asserts checking if a formatted date is returned from a class method TGigasecond.Add which takes a formatted date. Nothing is being checked in stdin/stdout.

Unfortnately I don’t understand what a class method means in this context. I’m used to it in visual basic where it’s a way of acting on things on the screen.

I’ve commented out the Ignores in uGigasectionTests.pas so the tests will run. I have my code in uGigasecond.pas. They both compile no problem. I have manually checked the dates contained in the testing file with my program and my program outputs the correct date and time - so it’s working.

I can’t figure out how the automated testing works so I can just run the unit tests. Basically I con’t figure out how to make it go and run against my program and see the results of the testing. Here are some specific questions.

  1. Where are the logs for the tests and what filename am I looking for?

  2. My program prompts the user to input the date to add the gigasecond to, then echo prints the date with the new one. I don’t understand how Assert works in terms of my program. How is it passing the test input date to my program? The exercise was pretty loose in terms of describing what to do (compute a gigasecond later) and it feels like maybe there is a specific way the tests are expecting the input date that I’m missing - like maybe my program should be accepting input through a command line parameter or something?

  3. Right now I am running the tests by just pushing the “Run without Debugging” button (the plain green play button) in the Delphi environment. Is that the correct way to run the tests?

Thanks.

Does this help?

Actually, it does. Basically, the unit tests establish the criteria for the program - it tells more specifically what it should do. So that’s good and now I get how that works.

However, I still don’t understand how to make the Unit tests actually run. How does the unit test “talk” to my program and where are the results of the unit test located?

I have no clue how Delphi works, but typically the unit tests are the program you run. The unit tests load/import your code and run your code using various inputs. It checks the results of your code and, (for most tracks), outputs the results to STDOUT/the terminal.

There should be a file named “dunitx-results.xml” after running the tests. Compile the project to run the tests, but the terminal window that opens won’t stay open very long. For best results, run the compiled executable in another terminal. The results in the window look something like this:

PS C:\Users\anagy\Desktop\Exercism\delphi\hello-world> .\HelloWorld.exe
**********************************************************************
*        DUnitX - (c) 2015-2020 Vincent Parrett & Contributors       *
*                                                                    *
*        License - http://www.apache.org/licenses/LICENSE-2.0        *
**********************************************************************

DUnitX - [HelloWorld.exe] - Starting Tests.

..
Tests Found   : 1
Tests Ignored : 0
Tests Passed  : 1
Tests Leaked  : 0
Tests Failed  : 0
Tests Errored : 0

That might be a valid way to approach the exercise, but that’s not what the test suite is expecting. You need to define a TGigasecond class with a method Add that takes a string representation of a date and optionally time. That method returns a string representation of that moment in time plus a gigasecond. For each test, the Assert method compares the results of calling that method with a particular string to another string. If the strings are the same, the test passes. Otherwise, it fails. It might be helpful to conceptualize this as you’re building a library that other code executes rather than a stand-alone program.

The tests are run when you compile the project, but running the executable again in a separate terminal will give you the best results. Otherwise, just read the results XML file.