Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I write a DSL in Perl?

Tags:

perl

dsl

We use Perl for GUI test automation. It has been very successful. We have written a very lightweight DSL kind of language for GUI testing. The DSL is very similar to a object model.

For example, we have an Application object at the root. Each property sheet in the application is a View object. Each page under the page is called Page object itself. From Perl we send commands to a GUI application and the GUI interpret the command and respond to the command nicely. To send a command we do the following:

socket_object->send_command("App.View2.Page2.Activate()")
socket_object->send_command("App.View1.Page3.OKBtn.Click()")

This is not very readable. Instead, I want to write a Perl DSL for App, View and Page. Does Perl provide some sort of DSL structure where I can do the following?

App.View2.Page2.Activate();
App.View1.Page2.Click();

Where App shall be an instance of the Application class. I have to get the object of View2 at run time.

How to use such a things?

like image 456
Krish Avatar asked Dec 05 '08 05:12

Krish


1 Answers

You can do almost anything in Perl. But you have to do some strange stuff to get Perl to perform with syntax that is just not Perl.

  • To handle exactly what you have there, you would have to a lot of advanced tricks, which are by definition not that maintainable. You would have to:

    • overload the concatenation operator '.' (requires a blessed reference)
    • turn strictures off or create an AUTOLOAD subs to allow for those bare words - of course, you could write subs for all of the words you wanted to use (or use the barewords module).
    • possibly, create multiple packages, with multiple AUTOLOADs
  • Another way is source filters, I can probably pick up a downvote just for mentioning this capability. So I wouldn't exactly recommend this approach for people who are asking for help. But it's out there. Source filters (and I've done my share) are just one of those areas where you can think you're too clever for your own good.

    Still, if you are interested in Perl as a DSL "host" language, then source filters aren't exactly off limits. However, limiting this to just what you show that you want to do, Perl6::Attributes will probably do most of what you would need right off the shelf. It would take the . and translate them into the "->" that Perl would understand. But you can still take a look at source filters to understand what's going on behind the scenes.

    I also don't want to leave this topic without suggesting that a lot of the frustration you could have generating your own source filter (which I advise NOT to do) is eased by using Damian Conway's Filter::Simple.

  • The simplest thing is to forgo the '.' operator and just instead expect Perl-looking code.

    App->View2->Page2->Activate(); 
    App->View1->Page2->Click();
    

    App would be either a package or a sub. Either defined in the current package or imported which returns an object blessed into a package with a View2 sub (possibly an AUTOLOAD sub) which returns either the name of a package or a reference blessed into a package, that understands Page2, and then finally the return from that would understand Activate or Click. (See the OO tutorial, if you need.)

like image 63
Axeman Avatar answered Oct 14 '22 11:10

Axeman