SlideShare a Scribd company logo
High-level web testing Peter Sergeant Contractor @ NET-A-PORTER
 
 
# $mech is a WWW::Mechanize subclass object $mech ->get( '/Fulfilment/Putaway?process_group=844284' ); print   Dumper   $mech ->as_data(); # Page contents as data $VAR1  = { 'metadata'  => { 'delivery_number'   =>  '615019' , 'process_group_id'   =>  '844284' , 'page_type'   =>  'Surplus' , 'Designer'   =>  'Rows' , 'Description'   =>  'New Description' , 'Colour'   =>  'Black' , 'Sales Channel'   =>  'MRPORTER.COM' }, 'item_list'  => [ { 'Size'  =>  'None/Unknown' , 'SKU'  =>  '2106034-001' }, { 'Size'  =>  'None/Unknown' , 'SKU'  =>  '2106034-005' } ] };
'Fulfilment/PackingException/ViewContainer'  => { auto_match  =>  qr!^/Fulfilment/PackingException/ViewContainer\?container_id=M\w+ $! , specification  => { orphaned_items  => { location  =>  'id("orphaned_items")' , transform  =>  'parse_table' , optional  =>  1 , }, shipment_items  => { location  =>  'id("shipment_items")' , transform  =>  'parse_table' , optional  =>  1 , }, cancelled_items  => { location  =>  'id("cancelled_items")' , transform  =>  'parse_table' , optional  =>  1 , }, } },
'Fulfilment/Packing/EmptyTote'  => { auto_match  => qr!^/Fulfilment/Packing/EmptyTote!, specification  => { totes  => { location  =>  'id("totes")' , transform  =>  'parse_simple_list' , }, }, },
=head2  parse_simple_list Return a simplified text representation of the li elements under a node. =cut sub  _xclient_parse_simple_list  { my  ( $self ,  $list_node ) =  @_ ; # Find the child elements  my   @li_elements  =  $list_node ->find_xpath( 'li' )->get_nodelist(); # Render them as text my   @simplified  =  map  { $self ->_xclient_trim_cell( $_ ->as_text) }  @li_elements ; # And give them back... return   \@simplified ; }
# Send the shipment ID $mech ->submit_form_ok({ with_fields  => { shipment_nr =  $shipment_id  } },  "Shipment ID submitted" );
# Check we're in the right place, and then submit the form unless  (  $mech ->uri->path  eq   '/Fulfilment/Selection'  ) { die   "Expecting to be on /Fulfilment/Selection, actually: "  . $mech ->uri->path } # Send the shipment ID $mech ->submit_form_ok({ with_fields  => { shipment_nr =  $shipment_id  } },  "Shipment ID submitted" );
# Check we're in the right place, and then submit the form unless  (  $mech ->uri->path  eq   '/Fulfilment/Selection'  ) { die   "Expecting to be on /Fulfilment/Selection, actually: "  . $mech ->uri->path } # Send the shipment ID $mech ->submit_form_ok({ with_fields  => { shipment_nr =  $shipment_id  } },  "Shipment ID submitted" ); # Check we didn't get any logical errors if  (  $mech ->as_data->error_message ) { die   "HTTP request passed, but the application complained: "  . $mech ->as_data->error_message; }
__PACKAGE__->create_fetch_method( method_name  =>  'flow_mech__fulfilment__packingexception' , page_description  =>  'packing Exception Page' , page_url  =>  '/Fulfilment/PackingException' ); __PACKAGE__->create_form_method( method_name  =>  'flow_mech__fulfilment__packingexception_comment' , form_name  =>  'add_comments' , form_description  =>  'add comment' , assert_location  => qr!^/Fulfilment/Packing/CheckShipmentException!, transform_fields  =>   sub   {  return  {  note_text  =>  $_ [ 1 ] } }, ); #------------------------------------------------------------------------------- $framework ->flow_mech__fulfilment__packingexception ->flow_mech__fulfilment__packingexception_comment( "The quick brown fox ran over the lazy sheep dog" ); #------------------------------------------------------------------------------- #  ->flow_mech__fulfilment__packingexception() #  Retrieving the packing Exception Page #  URL /Fulfilment/PackingException retrieved successfully via HTTP #  No status message shown #  Retrieved the packing Exception Page #  ->flow_mech__fulfilment__packingexception_comment( "Comment 1:70236" ) #  URL [/Fulfilment/Packing/CheckShipmentException] matched assertion #  Searching for the add comment form #  Submitting add comment form #  URL /Fulfilment/Packing/CheckShipmentException?shipment_id=1630767 retrieved successfully via HTTP #  No status message shown
# Look for our purchase order $flow ->flow_mech__goodsin__stockin ->flow_mech__goodsin__stockin_search({ purchase_order_number  =>  $purchase_order_id }); # Did we find it? is( $flow ->mech->as_data->{ 'products' }->[ 0 ]->{ 'PID' }, $product_id , "Found our product from the purchase order search" ); # Check the packing slip $flow ->flow_mech__goodsin__stockin_packingslip(  $flow ->stock_order->id ) # Is it sensible? is( $flow ->mech->as_data->{ 'product_data' }->{ 'Purchase Order' }->{ 'value' }, $purchase_order ->purchase_order_number, "Purchase order matched from Stock Order page" );
sub  create_form_method  { my  (  $class ,  %args  ) =  @_ ; # This is a good place to check a user is using it correctly... $class ->_auto_methods_check_params( \%args , { required  => [ qw/ method_name form_name form_description assert_location / ], optional  => [ 'form_button' ,  'transform_fields' ], }); $class ->meta->add_method( $args { 'method_name' } =>   sub   { my  (  $self ,  @user_options  ) =  @_ ; $self ->show_method_name(  $args { 'method_name' },  @user_options  ); $self ->assert_location(  $args { 'assert_location' } ) if   defined   $args { 'assert_location' }; my   $transformed_fields  =  $args { 'transform_fields' } ? $args { 'transform_fields' }->(  $self ,  @user_options  ) : {}; $self ->indent_note( "Searching for the  $args {'form_description'} form" ); my   $name  =  ref ( $args { 'form_name' })  eq   'CODE'  ? $args { 'form_name' }->(  $self ,  @user_options  ) : $args { 'form_name' }; my   $form  =  $self ->mech->form_name(  $name  ); unless  (  $form  ) { croak   "Couldn't find a form with name  $args {'form_name'}" ; } $self ->mech->set_fields(  %$transformed_fields  ); my   $button  =  ref ( $args { 'form_button' })  eq   'CODE'  ? $args { 'form_button' }->(  $self ,  @user_options  ) : $args { 'form_button' }; $self ->indent_note( "Submitting  $args {'form_description'} form" ); $self ->mech->submit_form( fields  =>  $transformed_fields , $button  ? (  button  =>  $button  ) : () ); $self ->note_status; return   $self ; } ); }
Come and work at Net-A-Porter We’re hiring It’s a lot of fun Nice offices

More Related Content

PPT
Os Nixon
ODP
HTML::FormHandler
PDF
Rugalytics | Ruby Manor Nov 2008
PPTX
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
PDF
Refactoring using Codeception
KEY
Keeping It Simple
PPT
Framework
PDF
PHP and Rich Internet Applications
Os Nixon
HTML::FormHandler
Rugalytics | Ruby Manor Nov 2008
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
Refactoring using Codeception
Keeping It Simple
Framework
PHP and Rich Internet Applications

What's hot (19)

PPTX
Views notwithstanding
PDF
Shortcodes In-Depth
PPTX
Сергей Иващенко - Meet Magento Ukraine - Цены в Magento 2
PDF
WordPress-Powered Portfolios
PDF
introduction to Django in five slides
PPT
What's new in Rails 2?
PDF
VoCamp Seoul2009 Sparql
ODP
Writing Maintainable Perl
PDF
Dealing With Legacy PHP Applications
PDF
PHP「参照渡しできるよ」(君の考えている参照渡しと同じとは言ってない)
PDF
Routing System In Symfony 1.2
ODP
State Machines to State of the Art
PDF
WordPress REST API: Expert Advice & Practical Use Cases
PPT
PDF
Storytelling By Numbers
PDF
The Critical Need for Encrypted Email and File Transfer Solutions
Views notwithstanding
Shortcodes In-Depth
Сергей Иващенко - Meet Magento Ukraine - Цены в Magento 2
WordPress-Powered Portfolios
introduction to Django in five slides
What's new in Rails 2?
VoCamp Seoul2009 Sparql
Writing Maintainable Perl
Dealing With Legacy PHP Applications
PHP「参照渡しできるよ」(君の考えている参照渡しと同じとは言ってない)
Routing System In Symfony 1.2
State Machines to State of the Art
WordPress REST API: Expert Advice & Practical Use Cases
Storytelling By Numbers
The Critical Need for Encrypted Email and File Transfer Solutions
Ad

Viewers also liked (8)

ODP
Avoiding common pitfalls of datetime from a webapp's perspective
PDF
A music-sharing model of crowdsourcing in museums by ADOMultimedia
PDF
Our local state, my, my - Understanding Perl variables
PPTX
A Wikipedian-in-Residence at the British Museum
PDF
Your first website in under a minute with Dancer
PDF
Why Twitter Is All the Rage: A Data Miner's Perspective
PDF
Exploring slides
PDF
Wroc.py #32: Microservices in flask
Avoiding common pitfalls of datetime from a webapp's perspective
A music-sharing model of crowdsourcing in museums by ADOMultimedia
Our local state, my, my - Understanding Perl variables
A Wikipedian-in-Residence at the British Museum
Your first website in under a minute with Dancer
Why Twitter Is All the Rage: A Data Miner's Perspective
Exploring slides
Wroc.py #32: Microservices in flask
Ad

Similar to High-level Web Testing (10)

PPT
Nine Ways to Use Network-Side Scripting
ODP
Exploiting the newer perl to improve your plugins
ODP
Architecting Web Services
ODP
Mechanize at the Ruby Drink-up of Sophia, November 2011
PDF
Magic of Ruby
PPT
Ontologizing Business Processes
ODP
Schenker - DSL for quickly creating web applications in Perl
ODP
SCDJWS 3. WSDL
PPT
Stop Making The Web Harder Than It Is; Real-world REST, HATEOAS, and Hypermed...
PDF
Orbitz and Spring Webflow Case Study
Nine Ways to Use Network-Side Scripting
Exploiting the newer perl to improve your plugins
Architecting Web Services
Mechanize at the Ruby Drink-up of Sophia, November 2011
Magic of Ruby
Ontologizing Business Processes
Schenker - DSL for quickly creating web applications in Perl
SCDJWS 3. WSDL
Stop Making The Web Harder Than It Is; Real-world REST, HATEOAS, and Hypermed...
Orbitz and Spring Webflow Case Study

Recently uploaded (20)

PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Approach and Philosophy of On baking technology
PPTX
Cloud computing and distributed systems.
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Encapsulation theory and applications.pdf
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
Programs and apps: productivity, graphics, security and other tools
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
cuic standard and advanced reporting.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Digital-Transformation-Roadmap-for-Companies.pptx
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Diabetes mellitus diagnosis method based random forest with bat algorithm
sap open course for s4hana steps from ECC to s4
Approach and Philosophy of On baking technology
Cloud computing and distributed systems.
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Encapsulation theory and applications.pdf
The Rise and Fall of 3GPP – Time for a Sabbatical?
Programs and apps: productivity, graphics, security and other tools
The AUB Centre for AI in Media Proposal.docx
Advanced methodologies resolving dimensionality complications for autism neur...
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
cuic standard and advanced reporting.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Reach Out and Touch Someone: Haptics and Empathic Computing

High-level Web Testing

  • 1. High-level web testing Peter Sergeant Contractor @ NET-A-PORTER
  • 2.  
  • 3.  
  • 4. # $mech is a WWW::Mechanize subclass object $mech ->get( '/Fulfilment/Putaway?process_group=844284' ); print Dumper $mech ->as_data(); # Page contents as data $VAR1 = { 'metadata' => { 'delivery_number' => '615019' , 'process_group_id' => '844284' , 'page_type' => 'Surplus' , 'Designer' => 'Rows' , 'Description' => 'New Description' , 'Colour' => 'Black' , 'Sales Channel' => 'MRPORTER.COM' }, 'item_list' => [ { 'Size' => 'None/Unknown' , 'SKU' => '2106034-001' }, { 'Size' => 'None/Unknown' , 'SKU' => '2106034-005' } ] };
  • 5. 'Fulfilment/PackingException/ViewContainer' => { auto_match => qr!^/Fulfilment/PackingException/ViewContainer\?container_id=M\w+ $! , specification => { orphaned_items => { location => 'id("orphaned_items")' , transform => 'parse_table' , optional => 1 , }, shipment_items => { location => 'id("shipment_items")' , transform => 'parse_table' , optional => 1 , }, cancelled_items => { location => 'id("cancelled_items")' , transform => 'parse_table' , optional => 1 , }, } },
  • 6. 'Fulfilment/Packing/EmptyTote' => { auto_match => qr!^/Fulfilment/Packing/EmptyTote!, specification => { totes => { location => 'id("totes")' , transform => 'parse_simple_list' , }, }, },
  • 7. =head2 parse_simple_list Return a simplified text representation of the li elements under a node. =cut sub _xclient_parse_simple_list { my ( $self , $list_node ) = @_ ; # Find the child elements my @li_elements = $list_node ->find_xpath( 'li' )->get_nodelist(); # Render them as text my @simplified = map { $self ->_xclient_trim_cell( $_ ->as_text) } @li_elements ; # And give them back... return \@simplified ; }
  • 8. # Send the shipment ID $mech ->submit_form_ok({ with_fields => { shipment_nr = $shipment_id } }, "Shipment ID submitted" );
  • 9. # Check we're in the right place, and then submit the form unless ( $mech ->uri->path eq '/Fulfilment/Selection' ) { die "Expecting to be on /Fulfilment/Selection, actually: " . $mech ->uri->path } # Send the shipment ID $mech ->submit_form_ok({ with_fields => { shipment_nr = $shipment_id } }, "Shipment ID submitted" );
  • 10. # Check we're in the right place, and then submit the form unless ( $mech ->uri->path eq '/Fulfilment/Selection' ) { die "Expecting to be on /Fulfilment/Selection, actually: " . $mech ->uri->path } # Send the shipment ID $mech ->submit_form_ok({ with_fields => { shipment_nr = $shipment_id } }, "Shipment ID submitted" ); # Check we didn't get any logical errors if ( $mech ->as_data->error_message ) { die "HTTP request passed, but the application complained: " . $mech ->as_data->error_message; }
  • 11. __PACKAGE__->create_fetch_method( method_name => 'flow_mech__fulfilment__packingexception' , page_description => 'packing Exception Page' , page_url => '/Fulfilment/PackingException' ); __PACKAGE__->create_form_method( method_name => 'flow_mech__fulfilment__packingexception_comment' , form_name => 'add_comments' , form_description => 'add comment' , assert_location => qr!^/Fulfilment/Packing/CheckShipmentException!, transform_fields => sub { return { note_text => $_ [ 1 ] } }, ); #------------------------------------------------------------------------------- $framework ->flow_mech__fulfilment__packingexception ->flow_mech__fulfilment__packingexception_comment( "The quick brown fox ran over the lazy sheep dog" ); #------------------------------------------------------------------------------- # ->flow_mech__fulfilment__packingexception() # Retrieving the packing Exception Page # URL /Fulfilment/PackingException retrieved successfully via HTTP # No status message shown # Retrieved the packing Exception Page # ->flow_mech__fulfilment__packingexception_comment( "Comment 1:70236" ) # URL [/Fulfilment/Packing/CheckShipmentException] matched assertion # Searching for the add comment form # Submitting add comment form # URL /Fulfilment/Packing/CheckShipmentException?shipment_id=1630767 retrieved successfully via HTTP # No status message shown
  • 12. # Look for our purchase order $flow ->flow_mech__goodsin__stockin ->flow_mech__goodsin__stockin_search({ purchase_order_number => $purchase_order_id }); # Did we find it? is( $flow ->mech->as_data->{ 'products' }->[ 0 ]->{ 'PID' }, $product_id , "Found our product from the purchase order search" ); # Check the packing slip $flow ->flow_mech__goodsin__stockin_packingslip( $flow ->stock_order->id ) # Is it sensible? is( $flow ->mech->as_data->{ 'product_data' }->{ 'Purchase Order' }->{ 'value' }, $purchase_order ->purchase_order_number, "Purchase order matched from Stock Order page" );
  • 13. sub create_form_method { my ( $class , %args ) = @_ ; # This is a good place to check a user is using it correctly... $class ->_auto_methods_check_params( \%args , { required => [ qw/ method_name form_name form_description assert_location / ], optional => [ 'form_button' , 'transform_fields' ], }); $class ->meta->add_method( $args { 'method_name' } => sub { my ( $self , @user_options ) = @_ ; $self ->show_method_name( $args { 'method_name' }, @user_options ); $self ->assert_location( $args { 'assert_location' } ) if defined $args { 'assert_location' }; my $transformed_fields = $args { 'transform_fields' } ? $args { 'transform_fields' }->( $self , @user_options ) : {}; $self ->indent_note( "Searching for the $args {'form_description'} form" ); my $name = ref ( $args { 'form_name' }) eq 'CODE' ? $args { 'form_name' }->( $self , @user_options ) : $args { 'form_name' }; my $form = $self ->mech->form_name( $name ); unless ( $form ) { croak "Couldn't find a form with name $args {'form_name'}" ; } $self ->mech->set_fields( %$transformed_fields ); my $button = ref ( $args { 'form_button' }) eq 'CODE' ? $args { 'form_button' }->( $self , @user_options ) : $args { 'form_button' }; $self ->indent_note( "Submitting $args {'form_description'} form" ); $self ->mech->submit_form( fields => $transformed_fields , $button ? ( button => $button ) : () ); $self ->note_status; return $self ; } ); }
  • 14. Come and work at Net-A-Porter We’re hiring It’s a lot of fun Nice offices