Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Myth of Untestable Code

The Myth of Untestable Code

Avatar for Sebastian Heuer

Sebastian Heuer

August 29, 2018
Tweet

More Decks by Sebastian Heuer

Other Decks in Technology

Transcript

  1. 1 <?php 2 use Content\CraftPaper\CraftPaper; 3 use Content\CraftPaper\InputTextFo; 4 use

    Content\DomainRemover\DomainRemover; 5 use Content\FlipCalendar\FlipCalendar; 6 use Content\FlipCalendar\Pdf; 7 use Content\FlipCalendar\ShellCommands; 8 use Content\Logging\Error; 9 use Content\Loggly\LogglyClient; 10 use Content\Loggly\LogglyToken; 11 use Content\RenderLock\FakeLock; 12 use Content\RenderLock\RealLock; 13 use Content\Shared\ConfigurationId; 14 use Content\Shared\ConfigurationIdChecker; 15 use Content\Shared\ConfigurationPathBuilder; 16 use Content\Shared\ContentDomain; 17 use Content\Shared\OrderItemId; 18 use Content\Shared\OrderToolDomain; 19 use Content\Shared\Status; 20 use Content\Shared\TemplatePath; 21 22 error_reporting(E_ALL); 23 24 ini_set('memory_limit', '2048M'); 25 ini_set('post_max_size', '64M'); 26 ini_set('upload_max_filesize', '64M'); 27 28 require_once '../../../config.php'; 29 require_once 'idml.php'; 30 require_once '../../../helper/logging/Logging.php'; 31
  2. (…) 2777 if ($isTranslationTool === false) { 2778 if (file_exists($configurationPath

    . 'spot' . $filenameSuffix . '.pdf')) { 2779 if ($isDebugMode) { 2780 echo $configurationPath . 'spot' . $filenameSuffix . '.pdf<br/>'; 2781 echo 'GENERATING PAGES ' . $i . ' spot.pdf<br/>'; 2782 } 2783 $pdf->setSourceFile($configurationPath . 'spot' . $filenameSuffix . '.pdf'); 2784 $tplIdx = $pdf->importPage($i + 1); 2785 $pdf->useTemplate($tplIdx, 0, 0); 2786 } elseif (file_exists($template_path . 'spot.pdf')) { 2787 if ($isDebugMode) { 2788 echo $template_path . 'spot.pdf<br/>'; 2789 echo 'GENERATING PAGES ' . $i . ' spot.pdf<br/>'; 2790 } 2791 $pdf->setSourceFile($template_path . 'spot.pdf'); 2792 $tplIdx = $pdf->importPage($i + 1); 2793 $pdf->useTemplate($tplIdx, 0, 0); 2794 } elseif ($isDebugMode) { 2795 echo 'NOT FOUND >> spot.pdf<br/>'; 2796 } 2797 } (…)
  3. FOUR HUNDRED TWENTY-TWO SEXVIGINTILLION, SIX HUNDRED THIRTEEN QUINVIGINTILLION, EIGHT HUNDRED

    SIX QUATTUORVIGINTILLION, SEVEN HUNDRED FIFTY-ONE TREVIGINTILLION, FOUR HUNDRED FORTY-SIX DUOVIGINTILLION, EIGHT HUNDRED FORTY-FOUR UNVIGINTILLION, THREE HUNDRED EIGHTY-THREE VIGINTILLION, SEVEN HUNDRED SEVENTY-SIX NOVEMDECILLION, EIGHT HUNDRED EIGHTY-NINE OCTODECILLION, FIVE HUNDRED FIFTY-FOUR SEPTENDECILLION, EIGHTY-ONE SEXDECILLION, NINE HUNDRED QUINDECILLION, ONE HUNDRED TWENTY-THREE QUATTUORDECILLION, FORTY-TWO TREDECILLION, SEVEN HUNDRED FIFTY-FOUR DUODECILLION, ONE HUNDRED EIGHT UNDECILLION, FIVE HUNDRED EIGHTY-THREE DECILLION, NINE HUNDRED FIFTY-EIGHT NONILLION, NINETY-THREE OCTILLION, SEVEN HUNDRED FIFTY-ONE SEPTILLION, ONE HUNDRED TWO SEXTILLION, THREE HUNDRED EIGHTY-FOUR QUINTILLION, NINE HUNDRED THREE QUADRILLION, SEVEN HUNDRED FIFTEEN TRILLION, THREE HUNDRED FORTY-THREE BILLION, FIVE HUNDRED SIXTY-FOUR MILLION, EIGHT HUNDRED THOUSAND
  4. ACCEPTANCE INTEGRATION UNIT END-TO-END do we write the right software?

    do we write the software right? execution time $$$ ¢ maintenance cost
  5. 1 <?php 2 class EndToEndTest extends PHPUnit\Framework\TestCase { 3 /**

    4 * @backupGlobals enabled 5 */ 6 public function testCreatesExpectedFoFile() { 7 8 $_REQUEST = [ 9 'template_design' => 'KAM11GG', 10 'template_format' => 'F210', 11 'template_color' => 'C06', 12 // (...) 13 ]; 14 15 require __DIR__ .'/../src/template_new.php'; 16 17 $expectedFile = __DIR__ . '/fixtures/expected.fo'; 18 $actualFile = __DIR__ . '/../data/templates/KAM11GG/F210/C06/input.fo'; 19 20 $this->assertFileEquals($expectedFile, $actualFile); 21 } 22 }
  6. 1 <?php 2 class EndToEndTest extends PHPUnit\Framework\TestCase { 3 4

    /** 5 * @backupGlobals enabled 6 * 7 * @dataProvider inputFoCreationTestProvider 8 * 9 * @param string $design 10 * @param string $format 11 * @param string $color 12 * @param string $expectedFile 13 */ 14 public function testCreatesExpectedInputFoFile($design, $format, $color, $expectedFile) { 15 16 $_REQUEST = [ 17 'template_design' => $design, 18 'template_format' => $format, 19 'template_color' => $color, 20 // (...) 21 ]; 22 23 require __DIR__ .'/../src/template_new.php'; 24 25 $actualFile = sprintf(__DIR__ . '/../data/templates/%s/%s/%s/input.fo', $design, $format, $color); 26 27 $this->assertFileEquals($expectedFile, $actualFile); 28 } 29 }
  7. CHARACTERIZATION TESTS "An attempt to lock existing behavior into an

    untested or undocumented system." http://wiki.c2.com/?CharacterizationTest
  8. 1 <?php 2 function add($a, $b) 3 { 4 return

    $a + $b; 5 } 6 7 add(1, 2); legacy.php
  9. $ php -d xdebug.auto_trace=1 -d xdebug.trace_format=1 \ -d xdebug.collect_params=5 -d

    xdebug.collect_return=1 legacy.php $ cat /tmp/trace.4251619279.xt Version: 2.5.3 File format: 4 TRACE START [2014-06-27 10:40:40] 1 0 0 0.000282 279896 {main} 1 /home/sb/legacy.php 0 0 2 1 0 0.000371 280136 add 1 /home/sb/legacy.php 7 2 aToxOw== aToyOw== 2 1 1 0.000440 280256 2 1 R aTozOw== 1 0 1 0.000470 280016 1 0 R aToxOw== 0.000648 8488 TRACE END [2014-06-27 10:40:40] $ de-legacy-fy generate-characterization-test add /tmp/trace.4251619279.xt CharacterizationTest CharacterizationTest.php de-legacy-fy 2.0.0 by Sebastian Bergmann. Generated class "CharacterizationTest" in file "CharacterizationTest.php"
  10. 1 <?php 2 class CharacterizationTest extends \PHPUnit\Framework\TestCase 3 { 12

    /** 13 * @return array 14 */ 15 public function provider() 16 { 17 return array( 18 array($this->decode('aTozOw=='), $this->decode('aToxOw=='), $this->decode('aToyOw==')) 19 ); 20 } 21 22 /** 23 * @param string $value 24 * @return mixed 25 */ 26 private function decode($value) 27 { 28 return unserialize(base64_decode($value)); 29 }
 30 31 32 33 34 35 36 37 38 } 31 /** 32 * @dataProvider provider 33 */ 34 public function testAddFunctionWorksLikeItUsedTo($expected, $a, $b) 35 { 36 $this->assertEquals($expected, add($a, $b)); 37 }
  11. 1 <?php 2 class TemplateNew { 3 public function execute()

    { 4 $oConfig = new Config(); 5 $configurationIdChecker = new ConfigurationIdChecker(); 6 7 /** 8 * @deprecated $_REQUEST['template_format']. Use $_REQUEST['format'] 9 * TODO see WEDS-609 10 */ 11 $templateFormatParameter = isset($_REQUEST['format']) ? $_REQUEST['format'] : $_REQUEST['template_format'] 12 /** 13 * @deprecated $_REQUEST['template_design']. Use $_REQUEST['design'] 14 * TODO see WEDS-609 15 */ 16 $templateDesignParameter = isset($_REQUEST['design']) ? $_REQUEST['design'] : $_REQUEST['template_design'] 17 /** 18 * @deprecated $_REQUEST['template_color']. Use $_REQUEST['color'] 19 * TODO see WEDS-609 20 */ 21 $templateColorParameter = isset($_REQUEST['color']) ? $_REQUEST['color'] : $_REQUEST['template_color']; 22 23 $basePath = substr($oConfig->getBasePath(), 0, -1); // remove ending slash 24 $configurationRoot = $oConfig->getConfigByPath('path/configurations'); 25 $templateRoot = ''; // setted up in line 382 (template switch) 26 $sFopConfigRelative = $oConfig->getConfigByPath('path/fop/config'); 27 $sFopConfigAbsolute = $basePath . '/' . $sFopConfigRelative; 28 $usedDieCut = (isset($_REQUEST['diecut']) && !empty($_REQUEST['diecut']) && 'D53' == $_REQUEST['diecut'] ? 29 $_REQUEST['diecut'] : ''); 30 $configurationID = (isset($_REQUEST['configurationID'])) ? $_REQUEST['configurationID'] : null;
  12. 1 <?php 2 class TemplateNew { 3 /** @var TemplateNewConfig

    */ 4 private $config; 5 /** @var IDML */ 6 private $idmlParser; 7 /** @var TemplateNewRequest */ 8 private $request; 9 10 /** 11 * @param TemplateNewConfig $config 12 * @param IDML $idmlParser 13 * @param TemplateNewRequest $request 14 */ 15 public function __construct(TemplateNewConfig $config, IDML $idmlParser, TemplateNewRequest $request) { 16 $this->config = $config; 17 $this->idmlParser = $idmlParser; 18 $this->request = $request; 19 } 20 21 public function execute() { 22 $configurationIdChecker = new ConfigurationIdChecker(); 23 24 $templateFormatParameter = $this->request->getFormat(); 25 $templateDesignParameter = $this->request->getDesign(); 26 $templateColorParameter = $this->request->getColor(); 27 28 $basePath = substr($this->config->getBasePath(), 0, -1); // remove ending slash 29 $configurationRoot = $this->config->getConfigByPath('path/configurations'); 30 $templateRoot = ''; // setted up in line 382 (template switch) 31 $sFopConfigRelative = $this->config->getConfigByPath('path/fop/config');
  13. ACCEPTANCE INTEGRATION END-TO-END do we write the right software? do

    we write the software right? execution time $$$ ¢ maintenance cost