Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

You don't provide any documentation for the package, but a rigorous test suite would ideally start by testing that the API for the package does actually exist. i.e. the constructor constructs an object, blessed into the right package; and each public method is callable.

Then you test the basic functionality of the package. In this case, it's a queue, so FIFO. So you'd put some stuff into it, and test that it comes out in the correct order.

A feature of the package is that it has a limited size, so you'd want to test that this limit is enforced - i.e. try enqueuing more items than the size limit, and checking that it blocks. I haven't done any threaded programming in Perl for years, but in my limited experience I'm not sure it's possible to do that test reliably as it may introduce race conditions. Keeping the items enqueued simple (e.g. integers), and sleeping for a second before testing that the queue is blocked seems to be sufficient protection against race conditions.

Here's a test script using no non-core modules (apart from Q.pm of course!)

use Test::More tests => 21; # Test that Q.pm actually compiles. BEGIN { use_ok 'Q' }; # Test that the API as documented still exists. my $q = new_ok Q => [5]; can_ok $q => 'nq'; can_ok $q => 'dq'; can_ok $q => 'n'; # Thread to add some numbers to the queue. my $enqueue = threads->create(sub { $q->nq($_) for 90..99; }); # Vulnerable to race conditions :-( sleep 1; ok !$enqueue->is_joinable, '$q->nq is waiting'; # This breaks encapsulation by peeking at the internals of $q. # But we want to figure out if $q is waiting at '95'. ok !(grep { $_==95 } @$q), '95 is not on $q yet'; # Numbers come out of the thread in the correct order: is $q->dq, $_, "got $_ from queue" for 90..99; # Queue should now be empty, so not waiting for anything. sleep 1; ok $enqueue->is_joinable, '$q->nq is no longer waiting'; $enqueue->join; # Test that "dq" blocks too. my $dequeue = threads->create(sub { # Add up the numbers we get from the queue. my $sum; $sum += $q->dq for 1..10; return $sum; }); # We've not added any numbers to the queue yet, so the queue # should be waiting. sleep 1; ok !$dequeue->is_joinable, '$q->dq is waiting'; # Push some numbers into the queue. These sum to 55. $q->nq($_) for 1..10; # Queue should have recieved all the numbers. sleep 1; ok $dequeue->is_joinable, '$q->dq is no longer waiting'; my $sum = $dequeue->join; is $sum, 55, 'result of calculation performed in $dequeue is correct';

Update: comments on the implementation are welcome...

It would be handy to have a few additional methods:

  • length - the current number of items in the queue.
  • max_length - the maximum number of items allowed in the queue.
  • is_full - sub is_full { $_[0]->length == $_[0]->max_length }
  • peek - return the item at the head of the queue, but without dequeueing.
  • peek_all - return the entire queue as a list, without dequeueing.

Many of the above are trivial to implement by inspecting @$q, however implementing them outside the package itself breaks encapsulation. If people using your module start relying on the internal details of how Q.pm works (that it uses an arrayref, and keeps its stats in the last two array elements, etc), this leaves you less freedom to refactor Q.pm in the future if you discover a more efficient way of doing it.

Not only would the above make the module more testable, they'd also make it more useful. As I said, I don't know an awful lot about Perl threading, but I know a bit about parsing, which also tends to operate on a FIFO queue. Parsers for pretty much any non-trivial language have a peek_token method or two hidden away somewhere, for using tokens further up the stream to disambiguate the current token.


In reply to Re: Testing methodology by tobyink
in thread Testing methodology by BrowserUk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (5)
As of 2024-04-16 17:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found