Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

rats (5689)

rats
  (email not shown publicly)

Journal of rats (5689)

Tuesday May 13, 2008
07:29 AM

Bertrand Meyer: 7 Principles of Software Testing

I can't find a link for a really useful article I received today via email on software testing. (Subscribe to Eiffelworld newsletter) (No attempt to insert whole article here, but here's the 7 principles. Read the article for explanations.)

Principle 1: Definition of software testing
To test a program is to try to make it fail.

Principle 2: Tests versus specs
Tests are no substitute for specifications. One can derive tests from specifications, not the other way around.

Principle 3: Regression testing
Any failed execution must yield a test case, to remain permanently part of the project's test suite.

Principle 4: Applying oracles
Determining success or failure of tests must be an automatic process.

Principle 5: Manual and automatic
An effective testing process must include both manually and automatically produced test cases.

Principle 6: Empirical assessment of testing strategies
Evaluate any testing strategy, however attractive it may appear in principle, through objective assessment based on explicit criteria and a reproducible testing process.

Principle 7: Assessment criteria
The most important property of a testing strategy is the number of faults (or, if faults are not directly measurable, failures) it uncovers as a function of testing time.

07:01 AM

Why I'm Passionate About Perl

brian d'foy asks people to submit answers/comments to above topic. Here's my take:
  • The person who introduced me to Perl showed me that... No one person introduced me to Perl. I was attempting to install a manufacturing package using the Unify RDBMS and was finding the C API hair-tearingly difficult to use. A developer for the package mentioned there was a new language called Perl and there was Unify-Perl available. (This was in 1990.)
  • I first started using Perl to... talk to a Unify RDBMS.
  • I kept using Perl because... Perl did garbage collection and I'd spent 15 years fighting C's malloc and free. I didn't do anything but manage memory for my C programs and Perl came along and I suddenly had 90% more time to write real code, not manage memory.
  • I can't stop thinking about Perl... because the syntax seems to align with how my ideas form (or maybe my thinking is now so warped towards Perl I can't think any other way).
  • I'm still using Perl because... I haven't found anything sufficiently compelling in other languages to make me want to switch. I spent a few months wrangling Python for a living but felt only relief when I was able to switch back to Perl.
  • I get other people to use Perl by... teaching in-house courses, always being ready to answer any questions about Perl wherever I work, writing new apps in Perl if language is not specified.
  • I also program in ... Python and ... JavaScript, but I like Perl better as... I can write whole solutions to problems in a few lines in Perl. (Ever tried writing a 'one-liner' in Python? It ain't pretty :-)
Thursday April 07, 2005
08:10 PM

Programmer flow

Yesterday was one of those days where I was in 'flow'. I was rewriting one of my early attempts. A changed requirement now forced me to generalise the process. Previously I used procedural code, copying an even earlier version of the script written by my predecessor here.

But yesterday I decided it had to be implemented with a reasonable design (and that means OO for me) instead of more ad-hocery on top of existing ad-hocery. I still wasn't sure how to implement my design but I started coding and put a stub class and/or method for everything which was still unclear. As I proceeded the design crystallised in front of me. The script is small enough to allow me to rewrite the whole class hierarchy within a couple of hours if necessary so I had no fear of refactoring and refactoring again.

When my alarm went off to remind me to go home, I realised I'd spent the whole day in 'flow', totally absorbed in the code.

It doesn't happen often but when it does it reminds me why I love programming.

Tuesday March 08, 2005
11:20 PM

OO as roadmap

I remember a comment Bertrand Meyer made in OOSC2 that OO design simply provides an orderly way of arranging all the bits and pieces of a program that get scattered all over the place in traditional/procedural programming. OOD gives a roadmap of where to find things.

A refactoring exercise yesterday is a classic example. The existing code seemed to be written by someone who was reluctant to use anything more complex than single index arrays and single key hashes to store the quite complex data being retrieved from the database. I replaced the single keys/indexes with equivalent [array]{hash}[array]{hash} structures. But then it became obvious I really needed to replace the structures with objects. The clincher was a 50-line sort routine which used splice()!! All the sort was doing was separating the jobs into today's and yesterday's and then sorting the two lists from latest to earliest but because of the tangled up structures it was really difficult to do this using 'sort grep @array'.

I created a Job class and then the sort reduced to two lines: one to select and sort the previous day's jobs; one to select and sort the current day's jobs. I then noticed six lines of code at the end of the old sort routine which calculated column breaks for displaying the jobs (and held the results in global variables!). Why were they there? Well I supposed they had to be somewhere and the sort routine was as good a place as any. Turns out the lines and global variables weren't even needed but you wouldn't realise this until the sort routine shrunk so dramatically.

I occasionally hear or read dismissive comments about OO. "I can write faster code using paradigm X or paradigm Y" sort of thing. But I use OO as a tool to help me order and arrange my thoughts. Thinking is hard and I'll use any help I can get. If, as a side-effect, I can reduce a 50-line chunk of code to 2 lines, well that's nice too.

Sunday March 06, 2005
06:41 PM

devel heaven for curmudgeons

My client has given developers a lot of liberty to set up the devel environment they like. Aside from the obvious Debian Linux and Apache, I've always used vi/vim for Perl code devel. I've tried some IDEs over the years but the learning curve was too low (i.e. too long to learn fully). I remember using ptkdb years ago and it was great but the next place I worked at wouldn't let me install Tk. So I've always tried to use the bare minimum toolset with Perl: vi/vim and perl -d.

However last year I decided that if I was going to use vim because it, like Perl, is available on every system I work with, I had better use it as efficiently as possible.

The first thing I looked at was the Best of Vim Tips. Oh! if only I had read it years ago...

Then I decided to search http://www.vim.org/ for Perl plugins. Jackpot! I found perl-support.vim and tagmenu.vim. Now I could churn out Perl code as fast as I could think.

The only annoyance for me was that the keyboard shortcut for tagmenu clashed with one in perl-support. So I opened tagmenu.vim with gvim (Escher's drawing of the hand drawing the hand comes to mind) and changed the shortcut. This meant I had to maintain my own version of tagmenu and I never got around to troubling the author to change it but tagmenu hadn't changed for years (note that: I could have used it *years* ago) so it wasn't urgent.

Well, frabjous day!, as part of this recent install I've installed a more recent version of perl-support and it no longer clashes with tagmenu. All those years of using vi and vim now pay off because I can write and test my Perl code and my HTML code with the minimum of keystrokes (think 'RSI') and I rarely have to think which keys to use anyway. And I don't have to take my hand off the keyboard to use the mouse.

Of course, this only benefits crusty old curmudgeons like me who've built up the keyboard habits.

Monday February 21, 2005
09:31 PM

Scraping HTML with XML::LibXML

Writing a test script to hit a webpage and scrape out enough from the HTML response to verify it is correct...

First test is to (stop and) start my fake xmlrpc server with the response file I want and confirm it's alive. Hmmm. RPC::XML t/* tests do lots of that so let's steal/borrow some code. Hmmm. Net is down (firewall machine again probably). minicpan to the rescue. Minicpan has saved my bacon so many times I've lost count...

Well that was relatively painless. Randy J Ray writes nice clean intelligible Perl code. My script loads an RPC::XML::Server with the canned methods and forks it to a background process then gets a page from my web app to confirm the xmlrpc server is running correctly.

Now comes the fun. I hate HTML scraping but if I have to do it, I really like to use XML::LibXML. Aside from being very fast at parsing (which isn't important for this app), I can use XPath notation to navigate the DOM tree and, even better, there's xsh to let me try out my XPaths interactively. Yes it's possible to read the HTML code and keep track of how many levels of table/tr/td you are down by hand but why waste hours when with xsh you can do this in minutes.

Ouch! A small problem. LibXML expects xhtml and crashes all over the place when I ask xsh to parse the HTML output of my webapp. Lucky(!) for me (another reason for choosing CGI::Application) I have moved all the HTML from the old webapp into HTML::Template templates. So it's really easy to rewrite it as xhtml using Vim. (I discovered after rewriting by hand that one of the options for tidy is --asxhtml. It outputs HTML as xhtml. Double d'oh!)

So now I've got clean xhtml output I can use xsh to navigate through the parsed tree and find the fields I expect to see in the page if the webapp is working correctly. The first one I want has an XPath of

/html/body/table/tr[2]/td[2]/form/a[6]

thanks to xsh. Glad I didn't have to work that one out by hand. It's a link to expand the tree. So I'll use WWW::Mechanize to click the link and grab the response and verify it returned the required number of tables in the correct order with the correct contents. And then on to the next test...

06:22 PM

Displaying a directory tree in a webpage

The client's webapp appearance is modelled on directory tree displays. Clicking on icons expands the branch and clicking on icons in the branch expands the subbranch and so on. Likewise clicking on the icon at the top of an expanded branch closes/collapses the branch. Each icon is a button and places a call to the webserver. I initially thought I would replace the icons/buttons with Javascript because the response would be much faster and (I thought) there was no need to bother the webserver. So I looked at half a dozen examples available on the Net. Some people even want you to pay for their scripts. The neatest one I found sets up a tree in the browser's DOM and then changes an attribute so the browser can see or not see the branch as it repaints the page. This is (largely) browser independent.

But this turned out to be all irrelevant. I didn't realise at first but have now discovered that the client's app refreshes its data via a web service call every time an icon is clicked. So I might as well process the expand/collapse calls on the webserver.

This is where the session handling becomes critical and why I'm glad I chose CGI::Application. I created a four-level array of hashes (Days/Branches/Jobs/Items) to hold the state of the display then having use'd CGI::Application::Plugin::Session earlier on I simply added two lines of code:

$self->session->param('DAYS', $self->{Days});

to save the array between calls and

$self->{Days} = $self->session->param('DAYS');

to retrieve it next time the page is called. Cookies and data serialisation and storage are all handled by the module. Ah laziness! Let me count thy ways!

05:34 PM

Faking a web service for testing

So how to write a dummy xmlrpc server? Obviously look in CPAN. Two modules grabbed my attention: SOAP::Lite and RPC::XML.

The old webapp uses XMLRPC::Lite (a subclass of SOAP::Lite) to access the web service so why not use XMLRPC::Lite in server mode? But RPC::XML::Server has a nice feature: add_method. Allows me to package my canned server responses as methods in external files and restart the server and it will read the external file and add the method to its available services. Very nice for automated testing. Test merely(!) has to start the xmlrpc server with a known response file, run the test on the webapp, print pass or fail then restart server with a different response file and so on.

Time passes...

RPC::XML::Server is definitely the way to go! Works well and I now have a controllable/configurable web service server for my tests.

05:16 PM

Testing a webapp

Another complication for me is that there are no automated tests for the existing app. Seems they tested by sitting one guy at one terminal to edit some test data and another guy at another terminal clicked the various buttons on the webpage to see that it responded appropriately. Not very efficient in my view (but I wasn't there when the deadline was a couple of hours away and reputations were on the line...)

So I need some repeatable automated tests to verify the rewrite at least does everything the old app did as well as being able to check the new stuff. I decided to write a controllable xmlrpc server to fake the real server. Two reasons for this: one is that I need to be able to repeat the information that the server hands my webapp (the real server data changes constantly (is that an oxymoron?)); and secondly the team handling the rewrite for the new processes are behind schedule and they can't give me the new data yet (at least the call names have been finalised) so I need a way to fake it.

I also want to have tests which automatically configure the server to supply known data then make a call on the webapp and scrape the results out of the HTML and verify the webapp has responded correctly. This is a job for Test::More, WWW::Mechanize. and Test::WWW::Mechanize

04:51 PM

A generic process control webapp?

The story continues...

I won't say who my client is in case I say something libellous (they're actually very nice people and I want to keep it that way) and the app could be used in a number of different situations. The app simply gives the current status of customers' jobs in a manufacturing process and allows an operator to redirect jobs from one machine to another or to another branch if total disaster has hit. Off the top of my head I can think of half a dozen uses: a quick copy or business card printer; various custom building products like garage doors or window frames; auditting a major organisation; an online grocery store; a fast food or table service restaurant chain. The list goes on and on.

The complication here is the client is moving from making/selling a single product to making/selling multiple products and they're also franchising the business and each franchisee will be able to customise the appearance of their web screens.

I've got the simplest part of the deal: modifying the webapp. The app uses xmlrpc calls to the manufacturing system and designing and modifying the interface to the machines is the hard part in my view.

Other developers here have raised the issue of making the system open source but the senior management hasn't made a decision yet.