Testing in the PHP w orld Marcus Brger PHP Qubec Conference 2007 - - PDF document

testing in the php w orld
SMART_READER_LITE
LIVE PREVIEW

Testing in the PHP w orld Marcus Brger PHP Qubec Conference 2007 - - PDF document

Testing in the PHP w orld Marcus Brger PHP Qubec Conference 2007 The need for Testing Why Test? Introduction to phpt Testing Marcus Brger Testing in the PHP World 2 Why Test? Programming often comes along with code


slide-1
SLIDE 1

Testing in the PHP w orld

Marcus Börger

PHP Québec Conference 2007

slide-2
SLIDE 2

Marcus Börger Testing in the PHP World 2

The need for Testing

  • Why Test?
  • Introduction to phpt Testing
slide-3
SLIDE 3

Marcus Börger Testing in the PHP World 3

Why Test?

  • Programming often comes along with code re-use

Code re-use comes along with code changes Code changes are changes

  • Even for a few code lines - looking is not enough

Names can mislead Code may have non obvious side effects

  • Sometimes code is designed for a limited domain

Increasing/ Changing that domain is error prone

  • Code interaction is often underestimated

A bug fix in one function may affect other functions

slide-4
SLIDE 4

Marcus Börger Testing in the PHP World 4

How to test

  • Testing after test log

Record problematic input actions and replay them

  • Automated testing

Integration/ System testing Function testing Unit testing Acceptance/ Requirements testing Regression Testing

slide-5
SLIDE 5

Marcus Börger Testing in the PHP World 5

Integration testing

  • Not only particular pieces but the whole

Major is to verify all parts work together When working on real data it can detect system issues

  • Often requires multiple test systems

A manual or automated log is required Usually performed/ organized by QA

Does the system work?

slide-6
SLIDE 6

Marcus Börger Testing in the PHP World 6

Function testing

  • Execute parts of API
  • Use common data (domain API is designed for)
  • Use code from observed bugs

Does the API work?

slide-7
SLIDE 7

Marcus Börger Testing in the PHP World 7

Unit testing

  • Execute testing on code

From single routines, to parts (usually not the whole) Test private stuff Analyze untouched code to write more tests

  • Analytically find test data
  • Use code from observed bugs

Does the code work?

slide-8
SLIDE 8

Marcus Börger Testing in the PHP World 8

Acceptance testing

Requirements engineering

Develop tests from requirements

  • Does it do what the customer wants?
slide-9
SLIDE 9

Marcus Börger Testing in the PHP World 9

Regression testing

Backwards compatibility test

Verify input against expected output

  • Does it still work as expected?
slide-10
SLIDE 10

Marcus Börger Testing in the PHP World 10

Non-functional testing

  • Performance
  • Stability
  • Usability
  • Stress-Testing
slide-11
SLIDE 11

Marcus Börger Testing in the PHP World 11

Test-driven development

  • Think what you want or review specs
  • Write tests
  • Develop code and test
  • Write more tests if you figure any weakness
slide-12
SLIDE 12

Marcus Börger Testing in the PHP World 12

phpt Testing

slide-13
SLIDE 13

Marcus Börger Testing in the PHP World 13

What is phpt Testing?

  • Easy 1 PHP script test system (run-tests.php)
  • Everything goes into one file (* .phpt)
  • Capable of testing any aspect of PHP
  • Regression testing with pattern & regex matching
  • Integrates with memcheck
  • Used on http: / / gcov.php.net
slide-14
SLIDE 14

Marcus Börger Testing in the PHP World 14

http: / / gcov.php.net

slide-15
SLIDE 15

Marcus Börger Testing in the PHP World 15

http: / / gcov.php.net

slide-16
SLIDE 16

Marcus Börger Testing in the PHP World 16

http: / / gcov.php.net

slide-17
SLIDE 17

Marcus Börger Testing in the PHP World 17

http: / / gcov.php.net

slide-18
SLIDE 18

Marcus Börger Testing in the PHP World 18

Test file names

  • Tests for bugs

bug< bugid> .phpt bug17123.phpt

  • Tests for functions

< functionname> .phpt dba_open.phpt

  • General tests for extensions

< extname> _< num> .phpt dba_003.phpt

  • Do not use any .php files for includes or alike
slide-19
SLIDE 19

Marcus Börger Testing in the PHP World 19

Getting started with phpt

Each test consists of several sections

Name Input Expected output

  • - TEST- -

Hel l o W

  • r l d
  • - FI LE- -

Hel l o W

  • r l d
  • - EXPECT- -

Hel l o W

  • r l d

Always output something that can be verified.

slide-20
SLIDE 20

Marcus Börger Testing in the PHP World 20

Getting started with phpt

  • Each test consists of several sections
  • The input is usually a php snippet
  • An additional empty line makes cvs happy
  • - TEST- -

Hel l o W

  • r l d
  • - FI LE- -

<?php echo " Hel l o W

  • r l d" ; ?>
  • - EXPECT- -

Hel l o W

  • r l d

Use only the long version

  • f the php script tag.
slide-21
SLIDE 21

Marcus Börger Testing in the PHP World 21

Getting started with phpt

  • Each test consists of several sections
  • The input is usually a php snippet
  • The expected out must not be fixed

Scanf-like expressions

  • - TEST- -

Hel l o W

  • r l d
  • - FI LE- -

<?php echo " Hel l o W

  • r l d
  • - EXPECTF- -

Par se er r or : synt ax er r or , unexpect ed $end i n %

  • s. php on l i ne %

d

Do not check directories in error messages.

slide-22
SLIDE 22

Marcus Börger Testing in the PHP World 22

Getting started with phpt

  • Each test consists of several sections
  • The input is usually a php snippet
  • The expected out must not be fixed

Scanf-like expressions

  • - TEST- -

Hel l o W

  • r l d
  • - FI LE- -

<?php echo " Hel l o W

  • r l d
  • - EXPECTF- -

Par se er r or : synt ax er r or , unexpect ed $end i n %

  • s. php on l i ne %

d

When executed, the test file has .php ending.

slide-23
SLIDE 23

Marcus Börger Testing in the PHP World 23

Getting started with phpt

  • Each test consists of several sections
  • The input is usually a php snippet
  • The expected out must not be fixed

Scanf-like expressions Regular expressoins

  • - TEST- -

Hel l o W

  • r l d
  • - FI LE- -

<?php echo " Hel l o W

  • r l d"
  • - EXPECTREG

EX- - Par se er r or : ( par se| synt ax) er r or , unexpect ed $end i n . * on . *

You can - but don't drop too much: It is "on line".

slide-24
SLIDE 24

Marcus Börger Testing in the PHP World 24

Use var_dump()

Usually output variables are verified by var _dum p var _dum p

Allows to check for exact type Allows to check for private/ protected properties

  • - TEST- -

Var _dum p

  • - FI LE- -

<?php var _dum p( NULL) ; Var _dum p( 0) ; Var _dum p( f al se) ; Var _dum p( " " ) ; ?>

  • - EXPECT- -

NULL i nt ( 0) bool ( f al se) st r i ng( 0) " "

When checking object IDs, use scanf/regex.

slide-25
SLIDE 25

Marcus Börger Testing in the PHP World 25

More scanf matching

  • Allows matching blocks of output

% s Any string % i Integers (includes "–") % d Numbers % f Floating point values % c Single characters % x Hexadecimal values % w Any amount of Whitespace % e DIRECTORY_SEPARATOR ('\ ' or '/ ').

  • Cannot verify complex output
  • - TEST- -

M

  • r e Test i ng
  • - FI LE- -

<?php $s = ' 123' ; var _dum p( st r _shuf f l e( $s) ) ; var _dum p( $s) ; ?>

  • - EXPECTF- -

st r i ng( 3) " % s" st r i ng( 3) " 123"

Do not use %d for string length, unless you have to.

slide-26
SLIDE 26

Marcus Börger Testing in the PHP World 26

More regex matching

  • Regex matching requires escaping
  • Full regex support
  • - TEST- -

M

  • r e Test i ng
  • - FI LE- -

<?php $s = ' 123' ; var _dum p( st r _shuf f l e( $s) ) ; var _dum p( $s) ; ?>

  • - EXPECTREG

EX- - st r i ng\ ( 3\ ) " [ 123] { 3} " st r i ng\ ( 3\ ) " 123"

Be as precise as possible in matching expressions.

slide-27
SLIDE 27

Marcus Börger Testing in the PHP World 27

More output matching

  • Huge output can be verified indirectly using md5
  • When using files delete them before and after
  • - TEST- -

O ut put val i dat i on usi ng m d5

  • - FI LE- -

<?php $dest = di r nam e( __FI LE__) . ' / bug22544. png' ; @ unl i nk( $dest ) ; i m agePng( i m ageCr eat eTr uecol or ( 640, 100) , $dest ) ; Var _dum p( m d5_f i l e( $dest ) ) ; @ unl i nk( $dest ) ; ?>

  • - EXPECT- -

St r i ng( 32) " 10a57d09a2c63f ad87b85b38d6b258d6"

Use dirname(__FILE__) as temporary directory.

slide-28
SLIDE 28

Marcus Börger Testing in the PHP World 28

More output matching

  • Huge output can be verified indirectly using md5
  • When using files delete them before and after
  • Move clean-up code into a special section
  • - TEST- -

O ut put val i dat i on usi ng m d5

  • - FI LE- -

<?php $dest = di r nam e( __FI LE__) . ' / bug22544. png' ; @ unl i nk( $dest ) ; i m agePng( i m ageCr eat eTr uecol or ( 640, 100) , $dest ) ; Var _dum p( m d5_f i l e( $dest ) ) ; ?>

  • - CLEAN- -

<?php @ unl i nk( di r nam e( __FI LE__) . ' / bug22544. png' ) ; ?>

  • - EXPECT- -

St r i ng( 32) " 10a57d09a2c63f ad87b85b38d6b258d6"

Hide potential notices using the @ operator.

slide-29
SLIDE 29

Marcus Börger Testing in the PHP World 29

When tests get bigger

The special section = = = DONE= = = ends the test

  • Only available in --FILE--
  • Anything below that will be ignored
  • - TEST- -

M

  • r e Test i ng
  • - FI LE- -

<?php $s = ' 123' ; var _dum p( st r _shuf f l e( $s) ) ; var _dum p( $s) ; ?> ===DO NE=== <?php exi t ( 0) ; ?>

  • - EXPECTF- -

st r i ng( 3) " % s" st r i ng( 3) " 123"

With exit() in tests, no memleaks get reported.

slide-30
SLIDE 30

Marcus Börger Testing in the PHP World 30

Stopping the compiler

  • Some --EXPECT-- prevent from running the phpt
  • Use pseudo function __HALT_CO

M PI LER( )

  • - TEST- -

Si m pl eXM L: At t r i but e cr eat i on

  • - FI LE- -

<?php $xm l = ' <?xm l ver si on=" 1. 0" encodi ng=" I SO

  • 8859- 1" ?><f oo/ >' ;

$sxe = si m pl exm l _l oad_st r i ng( $xm l ) ; $sxe[ " at t r " ] = " val ue" ; echo $sxe- >asXM L( ) ; __HALT_CO M PI LER( ) ; ?>

  • - EXPECT- -

<?xm l ver si on=" 1. 0" encodi ng=" I SO

  • 8859- 1" ?>

<f oo at t r =" val ue" / >

Here the '<?' in the output would prevent execution.

slide-31
SLIDE 31

Marcus Börger Testing in the PHP World 31

An alternative to --FILE--

Very specific to Bug # 35382

  • - TEST- -

Bug #35382 ( Com m ent i n end of f i l e pr oduces f at al er r or )

  • - FI LEEO

F- - <?php eval ( " echo ' Hel l o' ; / / com m ent " ) ; echo " W

  • r l d" ;

/ / l ast l i ne com m ent

  • - EXPECT- -

Hel l o W

  • r l d

Here the 't' of 'comment' is the very last test file byte.

slide-32
SLIDE 32

Marcus Börger Testing in the PHP World 32

Preconditions

  • Tests may have several preconditions
  • Include files are good for common preconditions
  • Output "skip" if a precondition is not met
  • Useful: f unct i on_exi st s

f unct i on_exi st s, ext ensi on_l oaded ext ensi on_l oaded, com par e_ver si on com par e_ver si on+ phpver si on phpver si on

  • - TEST- -

Check f or exi f _r ead_dat a, unusual I FD st ar t

  • - SKI PI F- -

<?php i f ( ! ext ensi on_l oaded( ' exi f ' ) ) di e( ' ski p exi f n/ a' ) ; ?>

  • - FI LE- -

<?php $e=exi f _r ead_dat a( di r nam e( __TEST__) . ' / t est . j pg' , ' ' , t r ue, f al se) ; var _dum p( $e[ ' I FD0' ] [ 0] , $e[ ' I FD0' ] [ 1] ) ; ?>

  • - EXPECT- -

st r i ng( 11) " I f d00000009" st r i ng( 19) " 2002: 10: 18 20: 06: 00"

Use die() and an explanation in –SKIPIF--.

slide-33
SLIDE 33

Marcus Börger Testing in the PHP World 33

Redirected tests

  • Some extensions are drivers to others (e.g. PDO)
  • The --REDIRECTTEST-- section replaces --FILE—

It gets evaluated and must return an array Entry ENV contains the environment Entry TESTS contains the test directory/ files

  • - TEST- -

SQ Li t e

  • - SKI PI F- -

<?php # vi m : f t =php i f ( ! ext ensi on_l oaded( ' pdo_sql i t e' ) ) pr i nt ' ski p' ; ?>

  • - REDI RECTTEST- -

/ / no st ar t t ag needed r et ur n ar r ay( ' ENV' => ar r ay( ' PDO TEST_DSN' => ' sql i t e: : m em

  • r y: ' ) ,

' TESTS' => ' ext / pdo/ t est s' ) ;

There is no --FILE-- section in redirect tests.

slide-34
SLIDE 34

Marcus Börger Testing in the PHP World 34

Optional Input sections

  • - PO

ST- -

POST variables to be passed to the test script.

  • - PO

ST_RAW

  • -

RAW POST data (doesn't set the Content-Type).

  • - G

ET- -

GET variables to be passed to the test script.

  • - STDI N- -

Data to be fed to the test script's standard input.

  • - I NI - -

php.ini settings (use one line per setting e.g. foo= bar).

  • - ARG

S- -

A single line defining the arguments passed to PHP.

  • - ENV- -

Configures the environment to be used for PHP.

slide-35
SLIDE 35

Marcus Börger Testing in the PHP World 35

The environment

  • TEST_PHP_EXECUTABLE

The test executable

  • TEST_PHP_CG

I _EXECUTABLE When --GET-- is used

  • TEST_PHP_USER

User directories

  • TEST_PHP_ARGS

Arguments to use

  • TEST_PHP_LOG_FORMAT

Output files to create

$> expor t TEST_PHP_EXECUTABLE=/ pat h/ t o/ m y/ php $> expor t TEST_PHP_CG I _EXECUTABLE=/ usr / bi n/ php- cgi $> expor t TEST_PHP_USER=/ m y/ t est / f i l e/ di r $> expor t TEST_PHP_ARG S=" - n –q" $> expor t TEST_PHP_LO G _FO RM AT=" " $> m ake t est

All environment variables can be used together.

slide-36
SLIDE 36

Marcus Börger Testing in the PHP World 36

Running the tests

  • Execute the script run-tests.php
  • Pass any number of directories or * .phpt files
  • Without any option all tests in current dir are run

$> php r un- t est s. php $> php r un- t est s. php t est s sapi ext $> php r un- t est s. php m yt est . phpt

For help use: php run-tests.php -h

slide-37
SLIDE 37

Marcus Börger Testing in the PHP World 37

Running the tests

  • Execute the script run-tests.php
  • Pass any number of directories or * .phpt files
  • Without any option all tests in current dir are run
  • You can create a list of failed tests for later use

$> php r un- t est s. php $> php r un- t est s. php t est s sapi ext $> php r un- t est s. php –w m yer r . l st m yt est . phpt $> php r un- t est s. php –l m yer r . l st

There is also –r and -a to work with lists.

slide-38
SLIDE 38

Marcus Börger Testing in the PHP World 38

Running the tests

  • Use –n to suppress INI usage
  • Use –d <f oo>=<bar > to specify INI entries
  • Use –q to be quiet – do not ask questions
  • Use –s to write result to a file
  • Use –m to run tests through valgrind (very slow)

$> php r un- t est s. php - n $> php r un- t est s. php –d zend. ze1_com pat i bi l i t y_m

  • de=1

$> php r un- t est s. php –q $> php r un- t est s. php –s m yt est . r es $> php r un- t est s. php - m

Files + directories must be put right of all options.

slide-39
SLIDE 39

Marcus Börger Testing in the PHP World 39

INI overwrites

Some INI entries are hard-coded

  • utput_handler=
  • pen_basedir=

safe_mode= 0 disable_functions=

  • utput_buffering= Off

error_reporting= 8191 display_errors= 1 log_errors= 0 html_errors= 0 track_errors= 1 report_memleaks= 1 report_zend_debug= 0 docref_root= docref_ext= .html error_prepend_string= error_append_string= auto_prepend_file= auto_append_file=

slide-40
SLIDE 40

Marcus Börger Testing in the PHP World 40

Output files

  • Use TEST_PHP_LOG_FORMAT to select output files

L Log file, all information in one file E Expected output (--EXPECT--) O Actual output D Difference from expected and actual output

  • Sometimes it helps to use diff command
  • diff –u test.exp test.out
  • Use --keep-[ all| php| skip| clean] to keep temp files
slide-41
SLIDE 41

Marcus Börger Testing in the PHP World 41

THANK YOU

  • This Presentation

http: / / somabo.de/ talks/

  • PHPT Documentation

http: / / qa.php.net/ write-test.php

  • PHPUnit

http: / / sebastian-bergmann.de/ talks/ 2006-11-02- PHPUnit.pdf

  • SimpleTest

http: / / www.lastcraft.com/ simple_test.php

  • Power PHP Testing

http: / / brainbulb.com/ power-php-testing.pdf