fREWdiculous!
10 Nov
I’ve kinda fallen off the blogging horse, but most of that is because I’ve been writing Open Source code in my freetime. I think generally that’s a worthwhile tradeoff, but I like blogging in general, when I have stuff to blog about, so I’m gonna try to mix in more blog posts; at least about what I’m doing.
The first thing I did was make a subclass of my DBIx::Class::Schema. It looks something like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | package A::SMSDB; use parent 'Lynx::SMS::Schema'; use String::Random qw(random_string random_regex); sub cat_init { my $self = shift; $self->deploy; $self->prepopulate; } sub init { my $class = shift; my $self = $class->connect('dbi:SQLite:dbname=:memory:'); $self->deploy; $self->prepopulate; return $self; } sub prepopulate { my $s = shift; $s->resultset('Type')->populate([ ['name'], ['SMS'], ['Phone'], ]); # there's more here, but you get the idea } sub populate_sms { my $self = shift; my $args = shift; state %bp = ( message_child_to_status_links => [{ status => { api_callback_id => '002',}, }], ); my $act = $args->{account}; my $amount = $args->{amount}; my $child_id = 1; $act->messages->create({ type => { name => 'SMS' }, message => 'THIS IS A TEST!', from_email => 'bogus@test.com', children => [map +{ phone_number => random_regex('1\d{9}'), to_name => random_regex('\w{20}'), child_id => $child_id++, %bp, }, ( 1 .. $amount )] }); } 1; |
This is generally a good idea even if you aren’t using Catalyst. Having a test sub-class of your schema allows you to put various helper methods on your schema just for testing, as well as handy ways to deploy the schema. Since I’m so early on with this project I’ve been redeploying the database a lot, so it’s been very helpful to have my tests all just call init at the start of the test.
Speaking of redeploying, I’ve also been using an in memory SQLite for my tests, which is very handy. At some point later I’ll switch it to the deployment database. To connect to an in memory database use “dbi:SQLite:dbname=:memory:” as your dsn and you’ll be golden.
The next thing I did was made a special catalyst config file just for tests. This is what it looks like right now:
1 2 3 4 5 6 7 8 9 10 | { "name":"Lynx::SMS", "Model::DB": { "schema_class":"A::SMSDB", "connect_info":{ "dsn":"dbi:SQLite:dbname=:memory:", "xdsn":"dbi:SQLite:dbname=testing.db" } } } |
First off, the changed schema_class means that now $c->model(‘DB’)->schema is my test schema, so I get all those extra methods. Also note the xdsn key in connect info. JSON doesn’t natively support comments, so this is my hacky way of putting in an alternate dsn which I use when I want to look at the database after the test has finished (and probably failed.)
Now to get the above to apply, first I save it to “lynx_sms_testing.json” and then, before loading up my catalyst app in the test, I put
1 2 | use lib 't/lib'; BEGIN { $ENV{LYNX_SMS_CONFIG_LOCAL_SUFFIX} = 'testing' } |
And then after loading catalyst I’ll do something along the lines of:
1 | Lynx::SMS->model('DB')->schema->cat_init; |
To generate and populate the database.
Of course a lot of this probably needs to start using some kind of fixture solution and put into a small module in t/lib so that I’m not copying around that BEGIN block in all of my controller tests, but this works for now and I’ll factor it into that once I have more than one controller test
22 Jul
I am just getting through chapter four of the Catalyst book and there are already a whole lot of things worth mentioning. My internet is currently at 50% packet loss because our wifi router is busted so this is pretty painful for me. So we’ll keep it short.
The book has a nice (very short) introduction to Moose. Not only is this good because Catalyst is now based on Moose, but also I would say you probably want your OO code to be based on Moose. There are times when you probably don’t want to use Moose, but there are also times when you don’t want to use strict. As a rule, use Moose for OO code.
There is also a very good introduction to usage of CPAN. A lot of us think that CPAN is our programming platform. Knowing how to use it is extremely important. It includes not just finding stuff on CPAN, but also ascertaining the quality of those modules, and how to install them. Very good information for a perl programmer.
In chapter 4 mst discusses how he writes tests (which can be slightly supplemented with his latest blog post) and it’s actually quite helpful. Some people write tests after writing their code and run the risk of forgetting to test at all (that’s me!) Other people are all hardcore TDD and write tests first, but that assumes that they have already thought through the interface for what they are writing. mst posits that it’s better to write your code, and “test” it from test files as you go. And test in this case means warns, Data::Dumps, whatever. After it works how you expect, you then take those warns and whatnot and translate them into ok’s, is’s, and cmp_deeply’s. It’s really much nicer than the alternative: build it all and see if it works. Try it!
Lastly, I really like how they represent code as diffs instead of monolithic code. Writing large swaths of code doesn’t work that well in real life. It works much better to do tiny changes and make sure they still compile, do what you want, etc.
But the book certainly isn’t perfect! There are some weird code layout issues, (p34, 36, 39, etc) and I am pretty sure I saw at least one syntax error (END__ instead of __END__).
So far though, I would say that the book is better than most programming books. Really, a lot of programming books need to be more like this, instead of focusing entirely on the arcana of one framework they should help you be a better programmer overall.
7 May
I work at a Microsoft Company more or less. We use SQL Server, IIS (moving to Apache…), and various flavors of Windows for all of our machines. I haven’t had the cojones to install Ubunutu on my desktop yet, so I am stuck with cygwin and friends. But the perl that runs my server is not in cygwin. That means that if I want to do valid testing I have to do it with the regular perl. I’ve tried running prove from the cygwin commandline, (ie, /cygdrive/c/usr/bin/perl/prove,) but it just hangs. So I just have to suck it up and run prove from cmd.
The color highlighting doesn’t work (or at least I couldn’t get it to) so with code that sometimes throws a lot of warnings (that’s intentional, I am testing croaks often) I see way too much noise to follow what’s going on. Redirection to the rescue! Instead of just running prove, I can run
1 | prove 2> foo |
instead and it redirects all of the warnings to the file foo. Although it’s obvious, it makes running tests that much easier, and I think running tests should really be the path of least resistance. So thank you DOS makers, for implementing STDERR redirection, I didn’t think you’d have done that, but you did.
6 May
Sometimes when I get close to the end of the day and it isn’t feasible for me to start on something new I expand on my current project’s test suite. Recently I worked on one of the (seemingly) more complex ones. Basically it tests one of our autocompleters to ensure that it will search for the name and also the public facing id of a certain field. The id part was easy.
The name part was significantly more complex, but not too bad really:
1 2 3 4 5 6 7 8 9 10 11 | my @data = $schema->resultset('Customer')-> autocomplete_search({ query => 'ame' })->all; cmp_deeply @data, all( array_each( methods( name => re(qr/.*ame.*/i) ) ) ), "Name matches query"; |
So basically what that does is ensure that all of the items in @data have a method that match the regex listed. It doesn’t care how many items are returned or any of the other details. Elegance!