testing untestable code - phpbnl11
DESCRIPTION
TRANSCRIPT
![Page 1: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/1.jpg)
Testing untestable codeStephan Hochdörfer, bitExpert AG
"Quality is a function of thought and reflection -
precise thought and reflection. That’s the magic."
Michael Feathers
![Page 2: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/2.jpg)
About me
Stephan Hochdörfer, bitExpert AG
Department Manager Research Labs
enjoying PHP since 1999
@shochdoerfer
![Page 3: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/3.jpg)
Warning! Use at your own risk...
![Page 4: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/4.jpg)
No excuse for writing bad code!
![Page 5: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/5.jpg)
Seriously, I am not kidding!
![Page 6: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/6.jpg)
Theory
"There is no secret to writing tests, there
are only secrets to write testable code!"Miško Hevery
![Page 7: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/7.jpg)
Theory
What is „untestable code“?
![Page 8: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/8.jpg)
s
Theory
What is „untestable code“?
„new“ is evil!
![Page 9: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/9.jpg)
Theory
What is „untestable code“?
![Page 10: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/10.jpg)
Theory
What is „untestable code“?
![Page 11: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/11.jpg)
Theory
"...our test strategy requires us to have more control or
visibility of the internal behavior of the system under test."Gerard Meszaros, xUnit Test Patterns: Refactoring Test Code
![Page 12: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/12.jpg)
Theory
Class toTest
Class toTestUnittest
Unittest
Requiredclass
Requiredclass
Requiredclass
Requiredclass
![Page 13: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/13.jpg)
Theory
Class totest
Class totestUnittest
Unittest
Requiredclass
Requiredclass
Requiredclass
Requiredclass
DatabaseDatabase
Externalresource
Externalresource
Requiredclass
RequiredclassRequired
class
Requiredclass Webservice
Webservice
![Page 14: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/14.jpg)
Theory
Class totest
Class totestUnittest
Unittest
Requiredclass
Requiredclass
Requiredclass
Requiredclass
DatabaseDatabase
Externalresource
Externalresource
Requiredclass
RequiredclassRequired
class
Requiredclass Webservice
Webservice
![Page 15: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/15.jpg)
Theory
How to achieve „testable“ code?
![Page 16: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/16.jpg)
Theory
How to achieve „testable“ code?
Refactoring
![Page 17: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/17.jpg)
Theory
"Before you start refactoring, check that you
have a solid suite of tests."Martin Fowler, Refactoring
![Page 18: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/18.jpg)
Testing „untestable“ PHP Code
Let the work begin...
![Page 19: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/19.jpg)
Testing „untestable“ PHP Code
Safty instructions
Do not change existing code!
![Page 20: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/20.jpg)
Testing „untestable“ PHP Code | __autoload
<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this->Engine = Engine::getByType($sEngine);
}
}
![Page 21: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/21.jpg)
Testing „untestable“ PHP Code | __autoload
How to inject a dependency? Use __autoload
<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this->Engine = Engine::getByType($sEngine);
}
}
![Page 22: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/22.jpg)
Testing „untestable“ PHP Code | __autoload
<?phpfunction run_autoload($psClass) {
$sFileToInclude = strtolower($psClass).'.php';if(strtolower($psClass) == 'engine') {
$sFileToInclude = '/custom/mocks/'.$sFileToInclude;}include($sFileToInclude);
}
// Testcasespl_autoload_register('run_autoload');$oCar = new Car('Diesel');echo $oCar->run();
![Page 23: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/23.jpg)
Testing „untestable“ PHP Code | include_path
<?phpinclude('Engine.php');
class Car {private $Engine;
public function __construct($sEngine) {$this->Engine = Engine::getByType($sEngine);
}}
![Page 24: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/24.jpg)
Testing „untestable“ PHP Code | include_path
<?phpinclude('Engine.php');
class Car {private $Engine;
public function __construct($sEngine) {$this->Engine = Engine::getByType($sEngine);
}}
How to inject a dependency? Manipulate include_path setting
![Page 25: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/25.jpg)
Testing „untestable“ PHP Code | include_path
<?phpini_set('include_path',
'/custom/mocks/'.PATH_SEPARATOR.ini_get('include_path'));
// Testcaseinclude('car.php');
$oCar = new Car('Diesel');echo $oCar->run();
![Page 26: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/26.jpg)
Testing „untestable“ PHP Code | include_path alternative
<?phpinclude('Engine.php');
class Car {private $Engine;
public function __construct($sEngine) {$this->Engine = Engine::getByType($sEngine);
}}
![Page 27: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/27.jpg)
Testing „untestable“ PHP Code | include_path alternative
<?phpinclude('Engine.php');
class Car {private $Engine;
public function __construct($sEngine) {$this->Engine = Engine::getByType($sEngine);
}}
How to inject a dependency? Custom Stream Wrapper behaviour
Idea by Alex Netkachov, http://www.alexatnet.com/node/203
![Page 28: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/28.jpg)
Testing „untestable“ PHP Code | include_path alternative
<?phpclass CustomFileStreamWrapper { private $_handler;
function stream_open($path, $mode, $options, &$opened_path) { stream_wrapper_restore('file');
// @TODO: modify $path before fopen $this->_handler = fopen($path, $mode); stream_wrapper_unregister('file'); stream_wrapper_register('file', 'CustomFileStreamWrapper'); return true; }
function stream_read($count) {}
function stream_write($data) {}
function stream_tell() {}
function stream_eof() {}
function stream_seek($offset, $whence) {}}
stream_wrapper_unregister('file');stream_wrapper_register('file', 'CustomFileStreamWrapper');
![Page 29: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/29.jpg)
Testing „untestable“ PHP Code | include_path alternative
<?phpclass CustomFileStreamWrapper {
private $_handler;
function stream_open($path, $mode, $options, &$opened_path) {stream_wrapper_restore('file');$this->_handler = fopen($path, $mode);stream_wrapper_unregister('file');stream_wrapper_register('file', 'CustomFileStreamWrapper');return true;
}
function stream_read($count) {$content = fread($this->_handler, $count);$content = str_replace('Engine::getByType', 'AbstractEngine::get',
$content);return $content;
}}
stream_wrapper_unregister('file');stream_wrapper_register('file', 'CustomFileStreamWrapper');
include('engine.php');?>
![Page 30: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/30.jpg)
Testing „untestable“ PHP Code
How to test private methods?
![Page 31: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/31.jpg)
Testing „untestable“ PHP Code
How to test private methods?
There`s no need to!
![Page 32: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/32.jpg)
Testing „untestable“ PHP Code
How to test private methods?
There`s no need to, but...
![Page 33: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/33.jpg)
Testing „untestable“ PHP Code | private vs. protected
<?phpclass CustomFileStreamWrapper {
private $_handler;
function stream_open($path, $mode, $options, &$opened_path) {stream_wrapper_restore('file');$this->_handler = fopen($path, $mode);stream_wrapper_unregister('file');stream_wrapper_register('file', 'CustomFileStreamWrapper');return true;
}
function stream_read($count) {$content = fread($this->_handler, $count);$content = str_replace('private function', 'public function',
$content);return $content;
}}
stream_wrapper_unregister('file');stream_wrapper_register('file', 'CustomFileStreamWrapper');
include('engine.php');?>
![Page 34: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/34.jpg)
Testing „untestable“ PHP Code | Namespaces
<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this->Engine = \Car\Engine::getByType($sEngine);
}}
![Page 35: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/35.jpg)
Testing „untestable“ PHP Code | Namespaces
<?phpclass Car {
private $Engine;
public function __construct($sEngine) {$this->Engine = \Car\Engine::getByType($sEngine);
}}
How to inject a dependency? Use __autoload or manipulate the include_path
![Page 36: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/36.jpg)
Testing „untestable“ PHP Code | vfsStream
<?phpclass Car {
private $Engine;
public function __construct($sEngine, $CacheDir) {$this->Engine = \Car\Engine::getByType($sEngine);
mkdir($CacheDir.'/cache/', 0700, true);}
}
![Page 37: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/37.jpg)
Testing „untestable“ PHP Code | vfsStream
How mock a filesystem? Use vfsStream - http://code.google.com/p/bovigo/
<?phpclass Car {
private $Engine;
public function __construct($sEngine, $CacheDir) {$this->Engine = \Car\Engine::getByType($sEngine);
mkdir($CacheDir.'/cache/', 0700, true);}
}
![Page 38: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/38.jpg)
Testing „untestable“ PHP Code | vfsStream
<?php
// setup vfsStreamvfsStreamWrapper::register();vfsStreamWrapper::setRoot(new vfsStreamDirectory('app'));
$oCar = new Car('Diesel', vfsStream::url('app'));
echo vfsStreamWrapper::getRoot()->hasChild('cache');
![Page 39: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/39.jpg)
Testing „untestable“ PHP Code | Database
Database Testing
Use the methods provided by your favourite framework
e.g Zend Framework
Implement Zend_Db_Statement_Interface
subclass Zend_Db_Adapter_Abstract
$db = new Custom_Db_Adapter(array());Zend_Db_Table::setDefaultAdapter($db);
![Page 40: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/40.jpg)
Testing „untestable“ PHP Code | Database
Database Testing
For low-level database access:
e.g MySQL
do not load the mysql extension
Add custom userland implementations of mysql_* functions
![Page 41: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/41.jpg)
Testing „untestable“ PHP Code | Database
Database Testing
Use the methods provided by your favourite unittest framework
e.g PHPUnit
extend PHPUnit_Extensions_Database_TestCase
implement getConnection() and getDataset()
![Page 42: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/42.jpg)
Testing „untestable“ PHP Code | Database
Database Testing
Use the methods provided by your favourite sql server (and tools)
e.g MySQL
use MySQL Proxy to transparently switch databases
Begin and rollback transactions
![Page 43: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/43.jpg)
Testing „untestable“ PHP Code
„I have no idea how to unit-test procedural code. Unit-testing assumes that I can instantiate a piece of my application in
isolation.“ Miško Hevery
![Page 44: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/44.jpg)
Testing „untestable“ PHP Code | Test functions
<?phpfunction startsWith($sString, $psPre) {
return $psPre == substr($sString, 0, strlen($psPre));}
function contains($sString, $sSearch) {return false !== strpos($sString, $sSearch);
}
![Page 45: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/45.jpg)
Testing „untestable“ PHP Code | Test functions
How to test PHPUnit can call functions
<?phpfunction startsWith($sString, $psPre) {
return $psPre == substr($sString, 0, strlen($psPre));}
function contains($sString, $sSearch) {return false !== strpos($sString, $sSearch);
}
![Page 46: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/46.jpg)
Testing „untestable“ PHP Code | Test functions
How to test PHPUnit can call functions
PHPUnit can save/restore globale state
<?phpfunction startsWith($sString, $psPre) {
return $psPre == substr($sString, 0, strlen($psPre));}
function contains($sString, $sSearch) {return false !== strpos($sString, $sSearch);
}
![Page 47: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/47.jpg)
Testing „untestable“ PHP Code | overwrite internal functions
<?phpfunction buyCar(Car $oCar) {
global $oDB;
mysql_query("INSERT INTO...", $oDB);
mail('[email protected]', 'New sale', '....');}
![Page 48: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/48.jpg)
Testing „untestable“ PHP Code | overwrite internal functions
<?phpfunction buyCar(Car $oCar) {
global $oDB;
mysql_query("INSERT INTO...", $oDB);
mail('[email protected]', 'New sale', '....');}
![Page 49: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/49.jpg)
Testing „untestable“ PHP Code | overwrite internal functions
<?phpfunction buyCar(Car $oCar) {
global $oDB;
mysql_query("INSERT INTO...", $oDB);
mail('[email protected]', 'New sale', '....');}
How to test Unfortunatley mail() is part of the PHP core and cannot be unloaded
![Page 50: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/50.jpg)
Testing „untestable“ PHP Code | overwrite internal functions
<?phpfunction buyCar(Car $oCar) {
global $oDB;
mysql_query("INSERT INTO...", $oDB);
mail('[email protected]', 'New sale', '....');}
How to test Use classkit extension to overwrite internal functions
![Page 51: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/51.jpg)
Testing „untestable“ PHP Code | overwrite internal functions
<?php
ini_set('runkit.internal_override', '1');
runkit_function_redefine('mail','','return true;');
?>
![Page 52: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/52.jpg)
Testing „untestable“ PHP Code
![Page 53: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/53.jpg)
What else?
Generating testable code
Remember: No changes to the source code!
![Page 54: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/54.jpg)
What else?
Generating testable code
Generative Programming
![Page 55: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/55.jpg)
Generating testable code
Generative Programming
ConfigurationConfiguration
Implementationcomponents
Implementationcomponents
Generatorapplication
Generatorapplication
ProductProductGenerator
Generator
1 ... n
![Page 56: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/56.jpg)
Generating testable code
Generative Programming
ConfigurationConfiguration
Implementationcomponents
Implementationcomponents
Generatorapplication
Generatorapplication
ApplicationApplication
GeneratorGenerator
TestcasesTestcases
![Page 57: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/57.jpg)
Generating testable code
Generative Programming
A frame is a data structure for representing knowledge.
![Page 58: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/58.jpg)
Generating testable code
FileFrm FILEIndex_php5 { private String Prefix = "test_"; private String MailSlot = "mail('[email protected]', 'New sale', '....');";
public FILEIndex_php5() {setFilename("index.php5");setRelativePath("/");
}
private void assign() {BEGINCONTENT()<?phpfunction buyCar(Car $oCar) {global $oDB;
<!{Prefix}!>mysql_query(„INSERT INTO...“, $oDB);<!{MailSlot}!>}
?>ENDCONTENT() }}
![Page 59: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/59.jpg)
Generating testable code
FileFrm FILEIndex_php5 { private String Prefix = "test_"; private String MailSlot = "mail('[email protected]', 'New sale', '....');";
public FILEIndex_php5() {setFilename("index.php5");setRelativePath("/");
}
private void assign() {BEGINCONTENT()<?phpfunction buyCar(Car $oCar) {global $oDB;
<!{Prefix}!>mysql_query(„INSERT INTO...“, $oDB);<!{MailSlot}!>}
?>ENDCONTENT() }}
![Page 60: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/60.jpg)
Generating testable code
Generative Programming
Extraction Show / hide parts of the code
ExampleMailSlot: mail('[email protected]', 'New sale', '....');
![Page 61: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/61.jpg)
Generating testable code
Generative Programming
Extraction Show / hide parts of the code
ExampleMailSlot: mail('[email protected]', 'New sale', '....');
<?phpfunction buyCar(Car $oCar) { global $oDB;
mysql_query("INSERT INTO...", $oDB); mail('[email protected]', 'New sale', '....');}
?>
![Page 62: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/62.jpg)
Generating testable code
Course of action
Customizing Change content of global vars Pre/Postfixes for own functions, methods, classes
ExamplePrefix: test_
![Page 63: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/63.jpg)
Generating testable code
Course of action
Customizing Change content of global vars Pre/Postfixes for own functions, methods, classes
ExamplePrefix: test_
<?phpfunction buyCar(Car $oCar) { global $oDB;
test_mysql_query("INSERT INTO...", $oDB);}
![Page 64: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/64.jpg)
Conclusion
How much effort to take?
![Page 65: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/65.jpg)
Conclusion
Conclusion
Change your mindset to write testable code!
![Page 66: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/66.jpg)
Conclusion
Conclusion
PHP is a swiss army knife.
![Page 67: Testing untestable code - PHPBNL11](https://reader031.vdocument.in/reader031/viewer/2022020306/547bf5ecb4af9fea158b4fc5/html5/thumbnails/67.jpg)
http://joind.in/2420