SlideShare a Scribd company logo
Testing Scripts
                      Randal L. Schwartz, merlyn@stonehenge.com
                             Version LT-1.05 on 13 Jun 2012

                         This document is copyright 2012 by Randal L. Schwartz, Stonehenge Consulting Services, Inc.
                 This work is licensed under Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License
                                               http://creativecommons.org/licenses/by-nc-sa/3.0/




Monday, June 25, 12                                                                                                        1
• Problem:
                       • Ya gotta test!
                      • Solution:
                       • use Test::More and friends
                      • But:
                       • What about scripts!


Monday, June 25, 12                                   2
• Problem:
                       • scripts are separate process
                       • hard to mock things
                      • Solution:
                       • Don’t use a separate process
                       • Require your script in your .t
                      • But:
                       • How will I invoke it then?

Monday, June 25, 12                                       3
• Problem:
                       • Loose code is effectively “main”
                      • Solution:
                       • Bundle loose code into a run subroutine:
                          sub run { ... }
                       • Also ensure true value at end of script
                      • But:
                       • What will invoke “run” then?

Monday, June 25, 12                                                 4
• Problem:
                       • Invoke “run” when run normally
                       • Don’t invoke “run” via require
                      • Solution:
                       • Use “caller”:
                          run(@ARGV) unless caller;
                      • But:
                       • What about namespace of .t file

Monday, June 25, 12                                       5
• Problem:
                       • Collision between script and .t names
                      • Solution:
                       • Bring it into its own package:
                            BEGIN {
                              package Program;
                              require "your-script";
                              die $@ if $@;
                            }
                      •   But:
                          • How to “invoke the program” from tests?


Monday, June 25, 12                                                   6
• Problem:
                       • Simulate execution
                      • Solution:
                       • Invoke run() with desired @ARGV:
                            subtest try_it => sub {
                              Program::run(qw(--foo --bar abc));
                            };
                      •   But:
                          • What about exceptions, exit, stdout?



Monday, June 25, 12                                                7
• Problem:
                       • Trapping everything (not just die)
                       • eval doesn’t cut it!
                      • Solution:
                       • Test::Trap!
                            use Test::Trap;
                            trap {
                              Program::run(qw(--foo --bar abc));
                            };
                      •   But:
                          • How will I know how the code finished?


Monday, June 25, 12                                                 8
• Problem:
                       • Was it normal exit, “exit”, or die?
                      • Solution:
                       • examine $trap object after trap { .. }
                            ok $trap->exit, 0, "exited 0";
                            like $trap->die, qr{missing args};
                      •   But:
                          • What about stdout, stderr, warnings?




Monday, June 25, 12                                                9
• Problem:
                       • What about those outputs?
                      • Solution:
                       • Test::Trap captures those too!
                            like $trap->stdout, qr{usage};
                            is $trap->stderr, q{}, "quiet errors";
                            is @{$trap->warn}, 1, "exactly 1 warn";
                      •   But:
                          • What about stubbing or mocking?



Monday, June 25, 12                                                   10
• Problem:
                       • Want to override some behavior
                      • Solution:
                       • Monkey patching!
                            subtest stub_it => sub {
                              local *Program::some_sub = sub { ... };
                              trap { Program::run() };
                            };
                      •   But:
                          • What about stdin?


Monday, June 25, 12                                                     11
• Problem:
                       • Provide stdin for script
                      • Solution:
                       • Small matter of programming:
                            local *STDIN;
                            open STDIN, "<", (my $S = join(q{}));
                            $$S .= "onentwonthreen";
                            trap { ... };
                            $$S .= "fournfiven"; trap { ... };
                      •   But:
                          • What about chdir?


Monday, June 25, 12                                                  12
• Problem:
                       • chdir has global effect
                      • Solution:
                       • Test::Trap is pluggable!
                          use Test::Trap::mine qw(:cwd);
                          trap { chdir "/tmp"; Program::run() };
                        • See my blog, or might be core now
                      • But:
                        • Does this really work for all scripts



Monday, June 25, 12                                                13
• Problem:
                       • Script might need complex interaction
                       • Maybe can’t edit code into run()
                       • Code might fork
                      • Solution:
                       • Yeah, traditional subprocesses
                       • Perhaps combined with Expect
                      • But:
                       • Test::Trap is amazingly useful!

Monday, June 25, 12                                              14
Follow me

                      •   Twitter: @merlyn
                      •   G+: Randal L. Schwartz
                      •   Personal blog: merlyn.posterous.com
                      •   http://blogs.perl.org/users/randal_l_schwartz/
                      •   merlyn, realmerlyn, or RandalSchwartz




Monday, June 25, 12                                                        15

More Related Content

PDF
Testing with Style @ Holidaycheck
PDF
ReactJS for Programmers
PDF
Testing, Learning and Professionalism — 20171214
PDF
(automatic) Testing: from business to university and back
PPTX
Test case, test sets and test scripts
DOC
Ap test script
PDF
Check printing in_r12
PDF
Best Practices for Testing in salesforce.com
Testing with Style @ Holidaycheck
ReactJS for Programmers
Testing, Learning and Professionalism — 20171214
(automatic) Testing: from business to university and back
Test case, test sets and test scripts
Ap test script
Check printing in_r12
Best Practices for Testing in salesforce.com

Similar to Testing scripts (20)

PPT
Perl Intro 4 Debugger
ODP
Red Flags in Programming
PDF
PPT
Perl Intro 3 Datalog Parsing
PDF
Lecture 22
PPT
7.1.intro perl
ODP
Perl - laziness, impatience, hubris, and one liners
PPT
Verilog Lecture5 hust 2014
PDF
TAP-Harness + friends
PPT
C tutorial
PDF
Perl Critic In Depth
PDF
Lecture19-20
PDF
Lecture19-20
PDF
Getting testy with Perl
KEY
Worst. Ideas. Ever.
PPT
Perl Intro 2 First Program
KEY
Good Evils In Perl (Yapc Asia)
KEY
Erlang bootstrap course
PPTX
Corinna-2023.pptx
PDF
What's New in Perl? v5.10 - v5.16
Perl Intro 4 Debugger
Red Flags in Programming
Perl Intro 3 Datalog Parsing
Lecture 22
7.1.intro perl
Perl - laziness, impatience, hubris, and one liners
Verilog Lecture5 hust 2014
TAP-Harness + friends
C tutorial
Perl Critic In Depth
Lecture19-20
Lecture19-20
Getting testy with Perl
Worst. Ideas. Ever.
Perl Intro 2 First Program
Good Evils In Perl (Yapc Asia)
Erlang bootstrap course
Corinna-2023.pptx
What's New in Perl? v5.10 - v5.16
Ad

More from Randal Schwartz (10)

PDF
Why Flutter.pdf
PDF
Native mobile application development with Flutter (Dart)
PDF
Git: a brief introduction
PDF
Perl best practices v4
PDF
A brief introduction to dart
PDF
My half life with perl
PDF
Intro to git (one hour version)
PDF
Introduction to git
ZIP
Introduction to Git
ZIP
Forget The ORM!
Why Flutter.pdf
Native mobile application development with Flutter (Dart)
Git: a brief introduction
Perl best practices v4
A brief introduction to dart
My half life with perl
Intro to git (one hour version)
Introduction to git
Introduction to Git
Forget The ORM!
Ad

Recently uploaded (20)

PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Electronic commerce courselecture one. Pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
Machine Learning_overview_presentation.pptx
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPTX
A Presentation on Artificial Intelligence
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
cuic standard and advanced reporting.pdf
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Spectral efficient network and resource selection model in 5G networks
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
MYSQL Presentation for SQL database connectivity
Digital-Transformation-Roadmap-for-Companies.pptx
The AUB Centre for AI in Media Proposal.docx
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Electronic commerce courselecture one. Pdf
Unlocking AI with Model Context Protocol (MCP)
gpt5_lecture_notes_comprehensive_20250812015547.pdf
“AI and Expert System Decision Support & Business Intelligence Systems”
Machine Learning_overview_presentation.pptx
Chapter 3 Spatial Domain Image Processing.pdf
A Presentation on Artificial Intelligence
NewMind AI Weekly Chronicles - August'25-Week II
Dropbox Q2 2025 Financial Results & Investor Presentation
Diabetes mellitus diagnosis method based random forest with bat algorithm
cuic standard and advanced reporting.pdf
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Spectral efficient network and resource selection model in 5G networks

Testing scripts

  • 1. Testing Scripts Randal L. Schwartz, merlyn@stonehenge.com Version LT-1.05 on 13 Jun 2012 This document is copyright 2012 by Randal L. Schwartz, Stonehenge Consulting Services, Inc. This work is licensed under Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License http://creativecommons.org/licenses/by-nc-sa/3.0/ Monday, June 25, 12 1
  • 2. • Problem: • Ya gotta test! • Solution: • use Test::More and friends • But: • What about scripts! Monday, June 25, 12 2
  • 3. • Problem: • scripts are separate process • hard to mock things • Solution: • Don’t use a separate process • Require your script in your .t • But: • How will I invoke it then? Monday, June 25, 12 3
  • 4. • Problem: • Loose code is effectively “main” • Solution: • Bundle loose code into a run subroutine: sub run { ... } • Also ensure true value at end of script • But: • What will invoke “run” then? Monday, June 25, 12 4
  • 5. • Problem: • Invoke “run” when run normally • Don’t invoke “run” via require • Solution: • Use “caller”: run(@ARGV) unless caller; • But: • What about namespace of .t file Monday, June 25, 12 5
  • 6. • Problem: • Collision between script and .t names • Solution: • Bring it into its own package: BEGIN { package Program; require "your-script"; die $@ if $@; } • But: • How to “invoke the program” from tests? Monday, June 25, 12 6
  • 7. • Problem: • Simulate execution • Solution: • Invoke run() with desired @ARGV: subtest try_it => sub { Program::run(qw(--foo --bar abc)); }; • But: • What about exceptions, exit, stdout? Monday, June 25, 12 7
  • 8. • Problem: • Trapping everything (not just die) • eval doesn’t cut it! • Solution: • Test::Trap! use Test::Trap; trap { Program::run(qw(--foo --bar abc)); }; • But: • How will I know how the code finished? Monday, June 25, 12 8
  • 9. • Problem: • Was it normal exit, “exit”, or die? • Solution: • examine $trap object after trap { .. } ok $trap->exit, 0, "exited 0"; like $trap->die, qr{missing args}; • But: • What about stdout, stderr, warnings? Monday, June 25, 12 9
  • 10. • Problem: • What about those outputs? • Solution: • Test::Trap captures those too! like $trap->stdout, qr{usage}; is $trap->stderr, q{}, "quiet errors"; is @{$trap->warn}, 1, "exactly 1 warn"; • But: • What about stubbing or mocking? Monday, June 25, 12 10
  • 11. • Problem: • Want to override some behavior • Solution: • Monkey patching! subtest stub_it => sub { local *Program::some_sub = sub { ... }; trap { Program::run() }; }; • But: • What about stdin? Monday, June 25, 12 11
  • 12. • Problem: • Provide stdin for script • Solution: • Small matter of programming: local *STDIN; open STDIN, "<", (my $S = join(q{})); $$S .= "onentwonthreen"; trap { ... }; $$S .= "fournfiven"; trap { ... }; • But: • What about chdir? Monday, June 25, 12 12
  • 13. • Problem: • chdir has global effect • Solution: • Test::Trap is pluggable! use Test::Trap::mine qw(:cwd); trap { chdir "/tmp"; Program::run() }; • See my blog, or might be core now • But: • Does this really work for all scripts Monday, June 25, 12 13
  • 14. • Problem: • Script might need complex interaction • Maybe can’t edit code into run() • Code might fork • Solution: • Yeah, traditional subprocesses • Perhaps combined with Expect • But: • Test::Trap is amazingly useful! Monday, June 25, 12 14
  • 15. Follow me • Twitter: @merlyn • G+: Randal L. Schwartz • Personal blog: merlyn.posterous.com • http://blogs.perl.org/users/randal_l_schwartz/ • merlyn, realmerlyn, or RandalSchwartz Monday, June 25, 12 15