Skip to content

ajborla/exercism-exercise-and-unit-tests-sample-for_Harbour

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

exercism-exercise-and-unit-tests-sample-for_Harbour

Sample exercises, unit tests, and test library, for proposed Exercism track, Harbour

author: Anthony J. Borla
contact: ajborla@bigpond.com
license: MIT

Overview

Language

Harbour is an open source port of, and 100% upwardly-compatible with, Clipper, an xBase-family language compiler that was popular in the mid-1980's through to mid- 1990's, for building database-driven, desktop applications on DOS-based (later Windows-based), x86 platforms.

The xBase language, itself, is simple, command-based, with in-built database creation and manipulation capablities, primarily intended for interactive use.

Clipper built on this, by borrowing and extending several C language features, to create a more general purpose, compiled programming language for application development. Harbour extends this capability to multiple platforms.

Anyone familar with C, or a similar, procedural language, will find little difficulty learning Harbour.

One possible starting point for doing so is: Wikibooks Clipper Tutorial.

Of course the prime source of information for all things Harbour is: Harbour Documentation

Test Library

The author was unable to source an official, let alone, any, unit test framework, therefore proceeded to implement one.

The result is, PRGUNIT, so-named because the extension for xBase source files is .prg.

It comprises approximately 80 lines of code, spread over several functions, all resident in the file, PRGUNIT.prg.

It is functional, insofar as it successfully tests all twenty one of the included exercises. Planned extensions (contingent on acceptance of Harbour as an Exercism track) include:

  • Support more data types
  • Emit TAP-compliant output
  • Emit Exercism spec-compliant JSON output

An unusual feature is the use of a database file to store unit test parameters. See the Usage section for more details.

Installation

The unit test library, unit tests, and Exercism exercises, are all resident in the current repository, and require no installation.

Harbour, however, does require installation. It is available in both binary, and source form.

Here is the official download page: Harbour Project

Binaries are available for several platforms, including DOS, Windows, OS/2 (an unsuccessful attempt by IBM to market a DOS-replacement), several Linux distributions, and MacOSX. Most of these date back several years, the most recent being the Ubuntu Linux version.

Binary installation involves downloading the relevant package, and using the relevant package manager to effect installation.

If targeting a recent Linux distribution, a source-based installation is straightforward, and, in the author's view, a preferable one.

Here is an example using the official source version (later versions are obtainable, refer installation instructions below). To download the source archive:

curl -sLk https://sourceforge.net/projects/harbour-project/files/source/3.0.0/harbour-3.0.0.tar.gz > harbour-3.0.0.tar.gz

Assuming the standard build tools (gcc, make) are installed (if not, follow instructions here: Install Development Tools), then perform the following steps:

tar -xzvf harbour-3.0.0.tar.gz && cd harbour-3.0.0
make && sudo make install

Several components will have installed in various subdirectories (the default parent directory location is /usr/local), the most important of which are the binaries, /usr/local/bin/hbrun and /usr/local/bin/hbmak2.

For additional information such as how to effect an installation on Windows, please refer to the following detailed instructions: Harbour Installation

Usage

Assuming command-line operation, and that the current directory points to a clone of this repository, the unit tests for an exercise, for example, the leap exercise, may be effected by invoking the hbrun binary, like so:

hbrun leap_test.prg

A successful execution will see generation of the following output:

OK - Year not divisible by 4: common year
OK - Year divisible by 2, not divisible by 4 in common year
OK - Year divisible by 4, not divisible by 100: leap year
OK - Year divisible by 4 and 5 is still a leap year
OK - Year divisible by 100, not divisible by 400: common year
OK - Year divisible by 100 but not by 3 is still not a leap year
OK - Year divisible by 400: leap year
OK - Year divisible by 400 but not by 125 is still a leap year
OK - Year divisible by 200, not divisible by 400 in common year

Continuing the current example, leap.prg, is the exercise file, and, of course, leap_test.prg is the test file, and is structured as follows:

* Variable declarations
memvar TESTS, SUCCESS

* Test database name
TESTS := "TESTS"

* Create tests database
do MakeTestDatabase with TESTS

* Add test data into tests database
do AddTestDatabase with TESTS, "Year not divisible by 4: common year", "==", ".F.", "LeapYear(2015)"
do AddTestDatabase with TESTS, "Year divisible by 2, not divisible by 4 in common year", "==", ".F.", "LeapYear(1970)"
do AddTestDatabase with TESTS, "Year divisible by 4, not divisible by 100: leap year", "==", ".T.", "LeapYear(1996)"
do AddTestDatabase with TESTS, "Year divisible by 4 and 5 is still a leap year", "==", ".T.", "LeapYear(1960)"
do AddTestDatabase with TESTS, "Year divisible by 100, not divisible by 400: common year", "==", ".F.", "LeapYear(2100)"
do AddTestDatabase with TESTS, "Year divisible by 100 but not by 3 is still not a leap year", "==", ".F.", "LeapYear(1900)"
do AddTestDatabase with TESTS, "Year divisible by 400: leap year", "==", ".T.", "LeapYear(2000)"
do AddTestDatabase with TESTS, "Year divisible by 400 but not by 125 is still a leap year", "==", ".T.", "LeapYear(2400)"
do AddTestDatabase with TESTS, "Year divisible by 200, not divisible by 400 in common year", "==", ".F.", "LeapYear(1800)"

* Execute unit tests
SUCCESS := RunTests(TESTS)

* Return success status to OS
ERRORLEVEL(IIF(SUCCESS, 0, 1))

* Code under test (CUT)
#include "leap.prg"

* Unit Test Framework
#include "PRGUNIT.prg"

The flow of control should be quite evident:

  • A database containing the unit test parameters is created
  • All unit tests in that database are serially executed
  • A success status is returned to the operating system, so assisting testing automation

Note that tests may be easily commented out, modified, and new tests added.

Note, also, that both the code under test (CUT), and unit test library source code, are included in the test file, as would any user-supplied utility files, should they be required.

The CUT source file may include procedures and functions in addition to the test function, but cannot contain global variables (these would need to be at the top of the test file).

Acknowledgements

The author frequently referred to, and adapted, the unit tests in the Exercism Bash Track. Many thanks to the authors of those tests for their work, particularly, the clarity of test names, and the addition of extra tests.

More generally, thanks to the volunteers who have, and continue to, develop Harbour, as well as those enthusiasts writing and hosting Harbour code and documentary resources, so helping to keep a historically rich, and important, legacy, alive into the 21st Century.

TODO

Assuming acceptance of this proposal, commence working on the newly-created repositories:

https://github.com/exercism/harbour

and:

https://github.com/exercism/harbour-test-runner

The author expects to effect the transference of current repository contents to the new track.

However, should there be interest, welcomes contributions in the form of new exercises. These should be quite straightforward to implement since committed exercises may be used as templates.

About

Exercism Track Proposal: Harbour

Resources

License

Stars

Watchers

Forks

Languages