RE: Fixtures

2007-02-16 Thread Ovid
--- Ovid [EMAIL PROTECTED] wrote:

 Later, the 'Our::Test::Database' has a DESTROY method which drops the
 database.  At the beginning and end of every .t file, the database is
 created from scratch and destroyed.

I forgot to mention something very important if you use this technique.
 We cache the parent process PID and in the destroy method, we verify
that the current PID matches the cached PID.  Otherwise, we do *not*
drop the database.  This is because forks can easily drop a database
when you didn't intend for this to happen.

Cheers,
Ovid

--

Buy the book -- http://www.oreilly.com/catalog/perlhks/
Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/


Re: Fixtures

2007-02-14 Thread Ovid
--- Thomas Klausner [EMAIL PROTECTED] wrote:
 I guess with some more fiddling the END-block could be made smart
 enough 
 to only tear down stuff that was actually set up, but it worked for 
 me...

If you're using a DB, you can use transactions (AutoCommit = 0) and
rollback at the end.

If you're using files, you can use File::Temp to automatically unlink
the file at the end of the test run.

In short, most things that we do in testing can be set up to clean up
automatically at the end of a test run.

Cheers,
Ovid

--

Buy the book -- http://www.oreilly.com/catalog/perlhks/
Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/


Re: Fixtures

2007-02-14 Thread Adrian Howard

Hiya,

On 13 Feb 2007, at 22:46, Kirrily Robert wrote:


Thanks all, especially Ovid who came closest to answering the actual
question, i.e. can someone explain it to me *in a perlish way*.   
Ovid's

example used Test::Class's setup/teardown;


You saying that T::C isn't Perlish? Wanna make something of it ;-)


would anyone else be able to
provide confirm that I'm making sense in the following
Test::Harness/Test::More style example:

1. Assume a test file t/foo.t
2. Assume a directory t/data (or t/fixtures if you will -- I just call
it data in my own tests).
3. Create a file t/data/foo.yml (or whatever data format)  
containing the

data needed by the tests in foo.t
4. At the beginning of foo.t, load data/foo.yml into whatever data
structure (memory, SQLite, real database, etc)
5. Run tests against foo.t
6. When foo.t exits, tear down the data created in step 4.

Yes?  In other words fixtures is just a jargony name for t/data/,
right?


Roughly yes.

And, is the above setup/teardown stuff right, or would you do it  
before

each individual test?  That would seem to be nearly nonsensical, but
then, I've seen stupider ideas.

[snip]

With an xUnit style you would do it before every test method, and  
each test method might have one or more assertions (which correspond  
roughly to what we call tests in the Perl world - something that  
pushes out an ok/not ok).


So, with a T::M style you might see something like;

sub make_fixture {
my $usd5 = Money-new( usd = 5 );
my $usd2 = Money-new( usd = 2 );
my $fr5 = Money-new( fr = 5 );
my $purse = Purse-new( usd = 2, fr = 1 );
}

{   diag 'can we add money to a purse';
my ($usd5, $usd2, $fr5, $purse) = make_fixture();
$purse-add( $usd5, $fr5 );
is $purse-amount( 'usd' ), 7, '$5 + purse with $2 = $7';
is $purse-amount( 'fr' ), 6, '5fr + purse with 1fr = 6fr';
}

{   diag 'can we take money out of a purse'
my ($usd5, $usd2, $fr5, $purse) = make_fixture();
my $m = $purse-remove( usd = 1 );
is_deeply $m, Money-new( usd = 1 ), 'took $1 out';
is $purse-amount( 'usd' ), 1, 'got $1 left'
}

It's not nonsensical because it allows you to write more isolated  
tests - which can give you more focused test results. If I keep my  
tests isolated then one test failing isn't going to make the whole  
script fail, and I can easily tweak tests early on in the script  
without worrying that it'll change test results further on.


Cheers,

Adrian


Re: Fixtures

2007-02-14 Thread Adrian Howard


On 13 Feb 2007, at 18:49, Eric Wilhelm wrote:
[snip]
How about, a thing into which the item under test gets inserted?   
The

c2 wiki (http://c2.com/cgi/wiki?TestFixture) has it as analogous to an
electronics test fixture.  They should probably include light  
fixture

as a very simple metaphor.  If you're testing electric lamps
(non-engineers usually call them light bulbs), you screw them into a
test fixture, plug it in, and flip the switch.  This emulates the
production environment, but with known variables (input voltage,
surface reflectance, etc) so you can measure the luminosity and verify
that it is within spec.

So, the fixture gives you the surrounding environment (and/or related
inputs, overrides CORE::GLOBAL::time and whatever), then your test  
just
involves one chunk of code and the direct inputs to it.  e.g. You  
might
have several fixtures, each of which creates an object with a known  
set

of attributes, then the tests call a method call on that object with
various parameters.

[snip]

That's it exactly. Especially that bit about multiple fixtures. Some  
people seem to get confused and try and test a class with one uber- 
fixture rather than build specialised ones.


Adrian


Re: Fixtures

2007-02-14 Thread Luke Closs

On 2/13/07, Kirrily Robert [EMAIL PROTECTED] wrote:


can someone explain it to me *in a perlish way*.



I think of fixtures as code that helps make testing data driven.  I haven't
used Test::Class (though I probably should sometime), but instead, I
refactor my unit tests into the simplest thing that would work.

I typically refactor unit tests first into functions at the bottom of the
t/*.t file, then to a t/TestUtil.pm (or somesuch), and then into a test
class if necessary.  Also, I also usually whip up mock libraries that
fixture code would use, and keep it in t/lib, and then 'use lib t/lib' in
my unit test files.

My favourite recent example was where I wrote unit tests for a search
feature, and I quickly wrote 100-ish different tests, based off of story
notes:

 Wildcard_tests: {
   search_ok( 'monkey', qr/Found 3 results/, ['Foo', 'Bar', 'Baz'] );
 }

 sub search_ok {
   # initialize search module
   # seed search results
   # perform search
   # perform test assertions
 }

Something like that.

I think this is also fixture-ish, as I'm making it really easy to test
additional lightbulbs.

Cheers,
Luke


Re: Fixtures

2007-02-13 Thread Ovid
--- Kirrily Robert [EMAIL PROTECTED] wrote:

 Does anyone here understand fixtures as a testing concept, and could
 they please explain it to me in a Perlish way?
 
 At least half of what I've heard described is what I usually achieve
 with a t/data/ directory, and another half is what I'd do by writing a
 specialized Test::Builder-based module.

A test fixture establishes a known state of a system.  For example, when
running with Test::Class, you can use setup and teardown methods which
run before and after every test to load test data in a  database, set up temp
files, or do anything necessary to start a known, stable state and later do
transaction rollbacks, clean up temp files and so on.

One of the reasons randomizing test runs is important is because they can
shake out bugs in the code when you have strange ordering dependencies, fail
to clean up temp files, alter global state, etc.  Test fixtures can make
finding such code errors even more reliable because they guarantee (to the
extent that they're not buggy) that every set of tests which runs has, if you
will, the same starting point.

Cheers,
Ovid

--

Buy the book -- http://www.oreilly.com/catalog/perlhks/
Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/


Re: Fixtures

2007-02-13 Thread Matisse Enzer


On Feb 12, 2007, at 10:35 PM, Kirrily Robert wrote:


Does anyone here understand fixtures as a testing concept, and could
they please explain it to me in a Perlish way?


One definition of a fixture comes from the Fitnesse system which is  
a framework for collaboration on acceptance testing.


Fitnesse makes it really easy for non-programmers to add assertions  
to a set of tests.


Typically the programmers provide a Fixture for each category of  
testing and the non-programers edit a wiki page to add rows to a  
table. Each row in the table on the wiki page is interpreted as a  
assertion and when you click the test button the Fitnesse framework  
executes the Fixture code, passing it the data from each row in the  
table.


It's much easier to see than to explain:

 http://fitnesse.org/FitNesse/FitNesse/FixtureCode


---
Matisse Enzer [EMAIL PROTECTED]
http://www.matisse.net/  - http://www.eigenstate.net/





Re: Fixtures

2007-02-13 Thread Ovid
--- Matisse Enzer [EMAIL PROTECTED] wrote:

 Typically the programmers provide a Fixture for each category of  
 testing and the non-programers edit a wiki page to add rows to a  
 table. Each row in the table on the wiki page is interpreted as a  
 assertion and when you click the test button the Fitnesse framework
 
 executes the Fixture code, passing it the data from each row in the  
 table.
 
 It's much easier to see than to explain:
 
   http://fitnesse.org/FitNesse/FitNesse/FixtureCode

Really? :)

java.lang.NullPointerException
fitnesse.wikitext.WidgetBuilder.addChildWidgets(Unknown Source)
fitnesse.wikitext.WidgetBuilder.addChildWidgets(Unknown Source)
fitnesse.wikitext.WidgetBuilder.addChildWidgets(Unknown Source)
fitnesse.wikitext.WidgetBuilder.addChildWidgets(Unknown Source)

Cheers,
Ovid

--

Buy the book -- http://www.oreilly.com/catalog/perlhks/
Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/


Re: Fixtures

2007-02-13 Thread chromatic
On Tuesday 13 February 2007 08:24, Ovid wrote:

 Really? :)

 java.lang.NullPointerException

Oh please, everyone knows Java doesn't have pointers!

-- c

OT - there are a lot of definitions of fixtures.  The best I've found 
is stuff tests share, which is exactly what Skud said.


Re: Fixtures

2007-02-13 Thread ben
On Tue, Feb 13, 2007 at 09:20:29AM -0800, chromatic wrote:
On Tuesday 13 February 2007 08:24, Ovid wrote:

 Really? :)

 java.lang.NullPointerException

Oh please, everyone knows Java doesn't have pointers!

Of course it does. They may not be accessible to the programmer 
due to the design of the bytecode, but they exist.

On a recent JRE I can even figure out the rough size of the stack
frame using a trick to get to a very limited piece of access to
the pointers.

Ben


Re: Fixtures

2007-02-13 Thread Michael G Schwern
[EMAIL PROTECTED] wrote:
 On Tue, Feb 13, 2007 at 09:20:29AM -0800, chromatic wrote:
 On Tuesday 13 February 2007 08:24, Ovid wrote:

 Really? :)

 java.lang.NullPointerException
 Oh please, everyone knows Java doesn't have pointers!
 
 Of course it does. They may not be accessible to the programmer 
 due to the design of the bytecode, but they exist.

Ben, please calibrate your sarcas-o-meter by setting one liner from chromatic 
to 100 and going from there. ;)


Re: Fixtures

2007-02-13 Thread Eric Wilhelm
# from Ovid
# on Tuesday 13 February 2007 01:16 am:

--- Kirrily Robert [EMAIL PROTECTED] wrote:
 Does anyone here understand fixtures as a testing concept, and
 could they please explain it to me in a Perlish way?

 At least half of what I've heard described is what I usually achieve
 with a t/data/ directory, and another half is what I'd do by writing
 a specialized Test::Builder-based module.

A test fixture establishes a known state of a system.  For example,
 when running with Test::Class, you can use setup and teardown
 methods which run before and after every test to load test data in a
  database, set up temp files, or do anything necessary to start a
 known, stable state and later do transaction rollbacks, clean up temp
 files and so on.

Good description, but I think teardown is (at least conceptually) part 
of setup.

How about, a thing into which the item under test gets inserted?  The 
c2 wiki (http://c2.com/cgi/wiki?TestFixture) has it as analogous to an 
electronics test fixture.  They should probably include light fixture 
as a very simple metaphor.  If you're testing electric lamps 
(non-engineers usually call them light bulbs), you screw them into a 
test fixture, plug it in, and flip the switch.  This emulates the 
production environment, but with known variables (input voltage, 
surface reflectance, etc) so you can measure the luminosity and verify 
that it is within spec.

So, the fixture gives you the surrounding environment (and/or related 
inputs, overrides CORE::GLOBAL::time and whatever), then your test just 
involves one chunk of code and the direct inputs to it.  e.g. You might 
have several fixtures, each of which creates an object with a known set 
of attributes, then the tests call a method call on that object with 
various parameters.

--Eric
-- 
Speak softly and carry a big carrot.
---
http://scratchcomputing.com
---


Re: Fixtures

2007-02-13 Thread Ian Langworth

On 2/12/07, Kirrily Robert [EMAIL PROTECTED] wrote:

Does anyone here understand fixtures as a testing concept, and could
they please explain it to me in a Perlish way?


In terms of etymology only, it was explained to me that the term
fixture comes from the idea of testing hardware components. You want
the environment to change as little as possible from component to
component, thus you build a fixture so that you may plug the component
in, test it, unplug it, and move onto the next.

--
Ian Langworth


RE: Fixtures

2007-02-13 Thread Kirrily Robert
Thanks all, especially Ovid who came closest to answering the actual
question, i.e. can someone explain it to me *in a perlish way*.  Ovid's
example used Test::Class's setup/teardown; would anyone else be able to
provide confirm that I'm making sense in the following
Test::Harness/Test::More style example:

1. Assume a test file t/foo.t
2. Assume a directory t/data (or t/fixtures if you will -- I just call
it data in my own tests).
3. Create a file t/data/foo.yml (or whatever data format) containing the
data needed by the tests in foo.t
4. At the beginning of foo.t, load data/foo.yml into whatever data
structure (memory, SQLite, real database, etc)
5. Run tests against foo.t
6. When foo.t exits, tear down the data created in step 4.

Yes?  In other words fixtures is just a jargony name for t/data/,
right?

And, is the above setup/teardown stuff right, or would you do it before
each individual test?  That would seem to be nearly nonsensical, but
then, I've seen stupider ideas.

My earlier comment about Test::Builder-based test modules was that some
of the fixtures stuff I've seen used repeated code chunks to go over the
contents of foo.yml, for instance doing validation runs against each
record, and it looked to me as if the Perlish way to do that is to write
a test module that provides record_is_valid() and related stuff.  As I
understand it now, this isn't actually part of fixtures conceptually,
it's just something that one might tend to see near fixtures.

K.



RE: Fixtures

2007-02-13 Thread leif . eriksen
 Ruby has a nice description at
http://manuals.rubyonrails.com/read/chapter/26

To quote
Fixtures is a fancy word for ‘sample data’. Fixtures allow you to populate 
your testing database with predefined data before your tests run.

Think about how something like Test::MockDBI's set_retval_arry() or 
set_retval_scalar() can be setup to return specific result sets for specific 
SQL queries - fixtures could be a nice way to modele creating this sample query 
result set.

L


-Original Message-
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] 
Sent: Tuesday, 13 February 2007 5:36 PM
To: perl-qa@perl.org
Subject: Fixtures

Does anyone here understand fixtures as a testing concept, and could they 
please explain it to me in a Perlish way?  

 

At least half of what I've heard described is what I usually achieve with a 
t/data/ directory, and another half is what I'd do by writing a specialized 
Test::Builder-based module.

 

K.

 

 


--
No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.1.411 / Virus Database: 268.17.33/678 - Release Date: 9/02/2007
 

-- 
No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.1.411 / Virus Database: 268.17.33/678 - Release Date: 9/02/2007
 
**
IMPORTANT
The contents of this e-mail and its attachments are confidential and intended
solely for the use of the individual or entity to whom they are addressed.  If
you received this e-mail in error, please notify the HPA Postmaster, [EMAIL 
PROTECTED],
then delete  the e-mail.
This footnote also confirms that this e-mail message has been swept for the
presence of computer viruses by Ironport. Before opening or using any
attachments, check them for viruses and defects.
Our liability is limited to resupplying any affected attachments.
HPA collects personal information to provide and market our services. For more
information about use, disclosure and access see our Privacy Policy at
www.hpa.com.au
**


RE: Fixtures

2007-02-13 Thread Ovid
--- Kirrily Robert [EMAIL PROTECTED] wrote:
 2. Assume a directory t/data (or t/fixtures if you will -- I just
 call
 it data in my own tests).
 3. Create a file t/data/foo.yml (or whatever data format) containing
 the
 data needed by the tests in foo.t
 4. At the beginning of foo.t, load data/foo.yml into whatever data
 structure (memory, SQLite, real database, etc)
 5. Run tests against foo.t
 6. When foo.t exits, tear down the data created in step 4.
 
 Yes?  In other words fixtures is just a jargony name for t/data/,
 right?

Pretty much, for the common sense that the term is often used (though
as noted people tend to have different definitions.
 
 And, is the above setup/teardown stuff right, or would you do it
 before
 each individual test?  That would seem to be nearly nonsensical, but
 then, I've seen stupider ideas.

Well, many languages consider a 'test' to be a set of asserts.  So with
Test::Class, the following would be considered *one* test by a Java
programmer but *four* tests by a Perl programmer:

  sub customer_name : Tests(4) {
  my $test  = shift;
  my $class = $test-testing_class;
  ok my $cust = $class-new('bob'), 
'Creating a new customer should work';
  isa_ok $cust, $class, '... and the object it returns';
  can_ok $cust, 'name';
  is $cust-name, 'bob', 
'... and it should return the correct name';
  }

That's one of the reasons for conceptual mismatches for different
programmers.

 My earlier comment about Test::Builder-based test modules was that
 some
 of the fixtures stuff I've seen used repeated code chunks to go over
 the
 contents of foo.yml, for instance doing validation runs against each
 record, and it looked to me as if the Perlish way to do that is to
 write
 a test module that provides record_is_valid() and related stuff.  As
 I
 understand it now, this isn't actually part of fixtures
 conceptually,
 it's just something that one might tend to see near fixtures.

Well, here's one way I do test fixtures with regular .t programs:

  use Test::More tests = 5;
  use Our::Test::Database;
  my ( $class, $dabase );
  BEGIN {
   $database = Our::Test::Database-new;
   $class = 'Customer';
   use_ok $class or die;
  }
  ok my $cust = $class-new('bob'), 
'Creating a new customer should work';
  isa_ok $cust, $class, '... and the object it returns';
  can_ok $cust, 'name';
  is $cust-name, 'bob', 
'... and it should return the correct name';

'Our::Test::Database' starts with something like (can't recall the
exact syntax) and use Template::Toolkit:

  DROP DATABASE [% test_database %] if exists;
  CREATE DATABASE [% test_database %];
  USE [% test_datbase %]

  # table definitions

Note that much of the above is simply handled for me with Test::Class,
but I tend to use Test::Class for OO tests and .t files for procedural
code.  It seems a better conceptual match.

Later, the 'Our::Test::Database' has a DESTROY method which drops the
database.  At the beginning and end of every .t file, the database is
created from scratch and destroyed.

You can also create a test helper module which can populate the
database with sample data (or at least static data which should always
exist), though this means that the programmer looking at a test doesn't
immediately see what data's in the database.

Cheers,
Ovid

--

Buy the book -- http://www.oreilly.com/catalog/perlhks/
Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/


Re: Fixtures

2007-02-13 Thread Thomas Klausner
Hi!

On Wed, Feb 14, 2007 at 09:46:19AM +1100, Kirrily Robert wrote:
 example used Test::Class's setup/teardown; would anyone else be able 
 to
 provide confirm that I'm making sense in the following
 Test::Harness/Test::More style example:

I had to do something similar just yesterday. I wrote a small testlib.pm
that does some setup with import() and some teardown in an END-block

In the test scripts I say:

  use lib qw(t);
  use testlib qw(things to setup);

in testlib.pm, the custom written import method sets up stuff according 
to the (slightly misused) import-list (eg qw(things to setup)). And the 
END-block just tears down everything (after checking it's there...)

I guess with some more fiddling the END-block could be made smart enough 
to only tear down stuff that was actually set up, but it worked for 
me...


-- 
#!/usr/bin/perl   http://domm.zsi.at
for(ref bless{},just'another'perl'hacker){s-:+-$-gprint$_.$/}