Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

Back when I first wrote ClarionTest, I only ever used it as a post-build task. That is, I'd build my test DLL and then I'd automatically call ClarionTest and load up my test DLL usually with the /run parameter to run all tests automatically. 

Later John Hickey made some nice improvements to ClarionTest, including adding the ability to watch a directory for changes and automatically load the changed test DLL. I never really used that option as the compile-automatically-run-tests-press-ESC-to-get-back-to-my-app cycle worked so well for me. 

And then after I adopted the practice of putting my classes in a separate DLL, I found myself doing a whole lot of testing that involved multiple changed DLLs - the class DLL and the unit tests DLL. My old test cycle wasn't so convenient when I was making changes only to the classes. 

It was time to revisit John's changes.

An all-source ClarionTest

A while back I took the radical step of converting ClarionTest from an APP file to an all-source project. I wasn't entirely sure at the time why I was doing it. In part it was a wild impulse to get my hands on the source code in a way not possible as long as it remained in an APP. 

But as I thought about this, I realized that ClarionTest really does belong as source code. It exists because I was fed up with having my business logic buried in embed points, and not only did I want to move that logic into reusable classes I also wanted to be able to test that business logic in some automated way. 

There were some odd contradictions in the first versions of ClarionTest. I realized that most of the business logic in ClarionTest itself was embed code. Perhaps that was an inevitable bit of bootstrapping, but once I had ClarionTest it made sense to move the app's own logic to ClarionTest, test it with ClarionTest, and then replace the ClarionTest embed code with the classes.'

Did that make any sense?

The more classes I write, and the more I learn about how I can write classes (there is always more to learn), the less satisfied I am with how the ABC class library (the foundation for the ABC templates) does things. That doesn't mean ABC is terrible code - it does lots of things well. But it's a pretty old design, and it does have some code smell. 

So why not make ClarionTest a showcase for all the things that are potentially great about Clarion object oriented programming, separation of concerns, and all those other technologies, techniques and practices that make for better software?

Given that premise, I ripped almost everything out of the ClarionTest source except for the window definitions and the data declarations necessary to compile those windows. And I started over.

Starting over (again and again)

Don't for a minute think that whatever I'm describing in the following text is the "final" version of ClarionTest. If anything, ClarionTest has been, is and will be in a state of evolution. There are compromises and failures in the current code. When I notice them I'll comment on them, and try give some reason for my choices. And I'll come back to the code periodically and complain about the crap I wrote last time. To paraphrase Anil Dash, writing code is all about trying to suck less. That doesn't mean I'm not ever happy with my code - I frequently sit back and look at something I've written with a great deal of satisfaction. But I know that just because it looks good now doesn't mean it will look equally good down the road.


  • Mark (and remember) the test DLL to be run
  • Mark (and remember) the individual tests that should be run
  • Display a summary of how many tests have failed and how many have passed
  • Option to display only the failed tests
  • Fix resizing so the last position/size is remembered

Reviewing the code

Diving into the ClarionTest source I noticed an implicit variable right off the bat. It was a simple one - just N#, hard to mess up. But implicits always worry me, and I already had an X variable so I changed all N# to X (after making sure I didn't have any nested loops where I'd already be using X). 

I also removed the XML configuration code (because it  and the web-style links, replacing them with buttons. 

Then I really started hacking away at the code. ClarionTest started out as an ABC app, which is really overkill for something that just shows a window with a few controls and does some pretty basic UI handling. There's all sorts of code there that simply isn't necessary, and again over time I would like ClarionTest itself to be something of a showcase for how you can build up an app using classes. 

So I ripped out all of the ABC code. 

 

 

Next up: some code to read a directory. You know the drill. Declare a queue:

AllFiles                                    QUEUE(File:queue),PRE(FIL)            !
											END                                   !

Then load up the queue:

	Free(AllFiles)
	DIRECTORY(AllFiles,CLIP(Set:FolderToMonitor) & '\*.DLL',ff_:DIRECTORY)

Simple enough, right? Silly to make that into a class, right?

Nah, turns out I have one on hand already that adds a few bells and whistles. Time to make it part of DCL!

That was easier said than done. My directory class, which also handles things like creating and removing directories, relies on several other classes which had to be brought in to DCL. In their previous ClarionMag incarnation I used some different naming standards and some of the include files had also changed. And then I had a problem with the Clarion CreateDirectory and RemoveDirectory functions, which confused me for a bit as the class has methods by those names also. I do use the Clarion functions as well and it turned out I had to add cwutil.clw to the project so the code would get compiled. 

I still have a problem with the directory class - one of the unit tests fails on an attempt to create a directory and then remove it when it isn't empty. But I'll have to leave that for another day. As an aside, one of my goals is to modify ClarionTest so I can execute a set of test DLLs and log the results - that will give me a view of which if any tests are failing throughout the system. 

So that was a lot of work just to replace a few lines of code, but it's all part of getting more ClarionMag code into DCL, so it's worth the effort. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • No labels