Web + Mobile Blog / Berlin http://www.sebastianviereck.de Coding, Hardware, Freelancing Fri, 26 May 2017 08:59:44 +0000 de hourly 1 http://wordpress.org/?v=3.5.1 Run PHPUnit Unit and Integrations test with different configurations in PHPStorm http://www.sebastianviereck.de/run-phpunit-unit-integrations-test-configurations-phpstorm/?utm_source=rss&utm_medium=rss&utm_campaign=run-phpunit-unit-integrations-test-configurations-phpstorm http://www.sebastianviereck.de/run-phpunit-unit-integrations-test-configurations-phpstorm/#comments Thu, 18 May 2017 09:29:02 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3291-de Weiterlesen ]]> If you want to develop unit and integration tests with PHPStorm you can easily bootstrap your application and run your tests. But if you want to develop real unit tests in your local development enviroment without having a database connection or a cache, you need to make sure, that your application is configured differently, when unit tests are running. In this article you will learn how to do that and how to make PHPStorm will automatically recognize which tests/tests suites you want to execute.

Requirement:

Your integration and unit tests are seperated in 2 directories, like:

/tests/unitTests
/tests/integrationsTests

Overview

There are 2 possibilities to configure PHPUnit to use different configurations:

First Option: Multiple phpunit.xml files

You can put 2 phpunit XML configuration files named integrationsTests.xml and unitTests.xml in your document root or in the folders /tests/unitTests or /tests/integrationsTests. The configurations files would look like this, with different bootstrap.php files, where you can load your configuration accodingly.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="phpunit.xsd"
       bootstrap="/tests/unitTests/bootstrap.php">
   <testsuites>
      <testsuite name="unitTests">
         <directory>/tests/unitTests</directory>
      </testsuite>
   </testsuites>
</phpunit>

The probnlem with this approach is, that PHPStorm is not able to automatically load the correct configuration file when you want to execute only one test class from e.g. the unit tests. You can only set one default configuration for all unit tests (PHPStorm: Run -> Edit Configuration-> Defaults -> PHPUnit)

phpsotrm_phpunit_default

PHPStorm default PHPUnit configuration

So when you execute a test file by right clicking on the test file or on the the test code and choose “Run”, than the unit test configuration is always executed.

So this option is not working with PHPStorm.

Second Option: Using a PHPUnit_Framework_BaseTestListener

This works with a single phpunit.xml, like this one

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="phpunit.xsd"
       bootstrap="/tests/bootstrap.php">
   <testsuites>
      <testsuite name="unitTests">
         <directory>/tests/unitTests</directory>
      </testsuite>
      <testsuite name="integrationTests">
         <directory>/tests/integrationTests</directory>
      </testsuite>
   </testsuites>
   <listeners>
      <listener  class="TestListener" file="/tests/TestListener.php"></listener>
   </listeners>
</phpunit>

And TestListener like this:

<?php

class TestListener extends PHPUnit_Framework_BaseTestListener {

   const UNIT_TEST_DIR_NAME = 'unitTests';
   const INTEGRATION_TEST_DIR_NAME = 'integrationTests';
   /**
    * @var bool whether to the configuration was already loaded, performance optimization
    */
   private static $configurationLoaded = false;

   /**
    * startTestSuite
    *
    * @param PHPUnit_Framework_TestSuite $suite
    * @return void
    */
   public function startTestSuite(PHPUnit_Framework_TestSuite $suite) {
      if(self::$configurationLoaded === false){
         //the suite is only set, when the whole suite is executed, not when a test of a suite is executed
         switch ($suite->getName()){
            case 'unitTests':{
               $this->loadUnitTestConfiguration();
               break;
            }
            case 'integrationTests':{
               $this->loadIntegrationTestConfiguration();
               break;
            }
            default:{
               $this->loadConfigurationByFilePath();
               break;
            }
         }
         self::$configurationLoaded = true;
      }
   }

   /**
    * loadConfigurationByFilePath 
    * 
    * @throws Exception
    * @return boolean
    */
   private function loadConfigurationByFilePath(){
      if($this->isTriggeredByIDE() && $this->isRunningOnCLI()){
         for($i = $_SERVER['argc']; $i > 0; $i--){
            $arg = strtolower($_SERVER['argv'][$i - 1]);
            if(stristr($arg, DIRECTORY_SEPARATOR . self::UNIT_TEST_DIR_NAME . DIRECTORY_SEPARATOR)){
               $this->loadUnitTestConfiguration();
               return true;
            }
            if(stristr($arg, DIRECTORY_SEPARATOR . self::INTEGRATION_TEST_DIR_NAME . DIRECTORY_SEPARATOR)){
               $this->loadIntegrationTestConfiguration();
               return true;
            }
         }
      }
   }

   /**
    * isTriggeredByIDE - looks for PHPStorm VAR
    *
    * @return boolean
    */
   private function isTriggeredByIDE(){
      return isset($_SERVER['IDE_PHPUNIT_PHPUNIT_PHAR']);
   }

   /**
    * isRunningOnCLI
    *
    * @return boolean
    */
   private function isRunningOnCLI(){
      return isset($_SERVER['argc']) && isset($_SERVER['argv']);
   }

   /**
    * loadUnitTestConfiguration
    *
    * @return void
    */
   private function loadUnitTestConfiguration(){
      //Stub, implement, if you like
   }

   /**
    * loadIntegrationTestConfiguration
    *
    * @return void
    */
   private function loadIntegrationTestConfiguration(){
      //Stub, implement, if you like
   }
}

This Listener is executed before every testsuite execution and can trigger a configuration to be loaded when a integration or a unit test is executed. With the help of this listener you can execute tests in PHPstorm with just on phpunit.xml file and have different unit test configurations.

You can use the /tests/bootstrap.php file to execute configrations which are the same and put different configurations in the methods loadUnitTestConfiguration and loadIntegrationTestConfiguration.

]]>
http://www.sebastianviereck.de/run-phpunit-unit-integrations-test-configurations-phpstorm/feed/ 0
PDOException: You cannot serialize or unserialize PDO instances http://www.sebastianviereck.de/pdoexception-serialize-unserialize-pdo-instances/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=pdoexception-serialize-unserialize-pdo-instances http://www.sebastianviereck.de/pdoexception-serialize-unserialize-pdo-instances/#comments Mon, 10 Apr 2017 14:12:20 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3283-de Weiterlesen ]]> Beim Mocken von Objekten mit PHPunit kann es zur Fehlermeldung:

PDOException: You cannot serialize or unserialize PDO instances

kommen, immer dann, wenn im Constructor eine PDO Instanz injeziert wird. Dies kann unterbunden werden durch:

class PDOMock extends PDO{
    public function __construct(){}
}
]]>
http://www.sebastianviereck.de/pdoexception-serialize-unserialize-pdo-instances/feed/ 0
NAS / externe Festplatte selbst retten und reparieren http://www.sebastianviereck.de/nas-externe-festplatte-selbst-retten-und-reparieren/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=nas-externe-festplatte-selbst-retten-und-reparieren http://www.sebastianviereck.de/nas-externe-festplatte-selbst-retten-und-reparieren/#comments Sun, 12 Mar 2017 23:25:36 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3256-de Weiterlesen ]]> Wenn einem mal wieder die Festplatte ohne Backup abgeschmiert ist oder das NAS einfach nicht mehr die Verbindung aufnehmen will zum eigenen Rechner, interessiert man sich für die Datenrettung von Festplatten.

Mit ein paar einfachen Schritten und Gadgets lässt sich das schnell von zu Hause aus machen.

1. Schritt: Externe Festplatte entkernen, NAS zerlegen

Dabei geht es genauso brutal zu, wie es sich anhört: Die modernen Verpackungen sind schwer zu knacken. Die Bergung der Festplatte aus dem Gehäuse ist oftmals schwieriger als gedacht, aber mit ein wenig Gewalt und Köpfchen möglch. Am wichtigsten ist, das Verstecke der kleinen Mini-Schraube zu finden, die hinter einem Aufkleber in der hintersten Ecke des Gehäuses zufällig platziert wurde, damit man sein Gerät auf jeden Fall nie wieder zusammen bauen kann.

Wenn man fertig ist mit seinem NAS sieht das in etwa so aus:

IMG_4954

Mein stark beschädigtes und garantiert nie mehr funktionsfähiges NAS, oben links ist die ausgebaute Festplatte zu sehen, die im nächsten Schritt ausgelesen wird. 3 Jahre hat es gehalten das Miststück, danke Samsung für den Müll

2. Schritt: Auslesen der Festplatte mit dem Kloner

Mit Hilfe des mega krassen Festplatten Klon Gadget kann man einfach seine Daten von der frisch freigelegten, ans Tageslicht geförderten Festplatte auf seinen Laptop sichern.

Einfach ein gleichgroße Festplatte kaufen und per Knopfdruck die Platte sichern oder einfach per USB im örtlichen PC einlesen lassen und die Daten sind wieder da.

3. Schritt: Software zur Datenwiederherstellung

Wenn die Hardware ok ist, kann man auch einfach mit einer Recovery-Software kostenlos seine Daten retten z.B. mit Recuva: Download bei Chip.de. Recuva stellt schon gelöschte Daten wieder her unter Windows und ist einfach zu bedienen.

Letzter Schritt: Ein ordentliches Gerät zulegen und sofort ordern bevor das nochmal passiert

Ich liebe Apple Time Capsule, auch wenn alles andere scheiße ist und geil aussieht, wie mein MacBook Pro: Apple Time Capsule ist ne geile Hardware und macht genau das, was es soll, nämlich alle Daten für ein komplettes Backup regelmäßig auf ein unabhängiges Gerät im Wlan zu sichern ohne rumzuzicken. Apple hats halt drauf was Einfachheit und geiles Design angeht:

Für alle User empfehle ich ein NAS mit mindestens 2 Festplatten gleicher Größe, die sich gegenseitig spiegeln und im Falle eines Crashes einer Festplatte kein Daten verlieren. Dieses wird genauso am Router per LAN verbunden und kann alle im Wlan befindlichen Geräte sichern. Die Software dazu wird meist gleich mitgeliefert.

]]>
http://www.sebastianviereck.de/nas-externe-festplatte-selbst-retten-und-reparieren/feed/ 1
PHP Wie verwendet man password_verify, password_hash und password_needs_rehash richtig http://www.sebastianviereck.de/php-wie-verwendet-man-password_verify-password_hash-und-password_needs_rehash-richtig/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=php-wie-verwendet-man-password_verify-password_hash-und-password_needs_rehash-richtig http://www.sebastianviereck.de/php-wie-verwendet-man-password_verify-password_hash-und-password_needs_rehash-richtig/#comments Tue, 28 Feb 2017 14:37:53 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3230-de Weiterlesen ]]> Mit der ab PHP 5.5. eingeführten Passwort-Hash Funktionalität kann man das Problem umgehen, dass ständig neue Hash Funktionen benutzen werden müssen, weil die alte zu leicht knackbar ist.

Bei bestehenden Projekten steht man dann an dem Punkt, wo man bestehenden Hashes in der Datenbank hat und diese nicht einfach neu hashen kann, weil man den Klartext nicht kennt. Diese Funktionalität wird einem durch die neue password_verify Funktion abgenommen.

So könnte ein neues Login-Funktion aussehen, welches dieses Problem umgeht. Beim Anheben der Hash-Sicherheit (Zeitdauer zum Berechnen des Hashes) kann man den Wert $currentHashOption['cost'] erhöhen

$username = '';
$password = 'xxxxxx';

$user = User::findByName($username);

if(password_verify($password, $user->password_hash) === false){
 throw new Exception('Invalid Login');
}
$currentHashAlgorithm = PASSWORD_DEFAULT;
$currentHashOption = ['cost' => 15];

$passwordsNeedsRehash = password_needs_rehash(
 $user->password_hash,
 $algorithm = $currentHashAlgorithm,
 $currentHashOption
);
if($passwordsNeedsRehash === true){
 $user->password_hash = password_hash($password, $currentHashAlgorithm, $currentHashOption);
 $user->save();
}
]]>
http://www.sebastianviereck.de/php-wie-verwendet-man-password_verify-password_hash-und-password_needs_rehash-richtig/feed/ 0
Analyse von sehr großen gzip/bzip2 gepackten Log-Dateien per Stream http://www.sebastianviereck.de/analyse-von-sehr-grossen-bzip2-gepackten-log-dateien-stream/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=analyse-von-sehr-grossen-bzip2-gepackten-log-dateien-stream http://www.sebastianviereck.de/analyse-von-sehr-grossen-bzip2-gepackten-log-dateien-stream/#comments Tue, 28 Feb 2017 13:42:55 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3226-de Weiterlesen ]]> Man kann per Stream in PHP beim verarbeiten der Daten sehr große Log-Dateien, die mehrere GB groß sind, sehr leicht analysieren mit Hilfe von Stream Compression Filter.

Damit kann die Datei ohne sie komplett in den Speicher laden zu müssen entpackt und analysiert werden beim Einlesen der Datei.

Dadurch kann man während des einlesens der Log-Datei schon nach beliebigen Stellen im Code suchen:

$file = 'X:/file.log.bz2';
$searchString = '2017-01-01';

if(file_exists($file)){
   $handle = fopen($file, 'r');
   stream_filter_append($handle, 'bzip2.decompress');
   while(!feof($handle)){
      $line = fgets($handle);
      if(strpos($line, $searchString) !== false){
         echo $line;
      }
   }
   fclose($handle);
}
]]>
http://www.sebastianviereck.de/analyse-von-sehr-grossen-bzip2-gepackten-log-dateien-stream/feed/ 0
Warum man Software Projekte nicht bei Agenturen entwicklen lassen sollte http://www.sebastianviereck.de/warum-man-software-projekte-nicht-bei-agenturen-entwicklen-lassen-sollte/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=warum-man-software-projekte-nicht-bei-agenturen-entwicklen-lassen-sollte http://www.sebastianviereck.de/warum-man-software-projekte-nicht-bei-agenturen-entwicklen-lassen-sollte/#comments Sun, 26 Feb 2017 10:32:48 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3220-de Weiterlesen ]]> Agenturen beschäftigen meist Freelancer, die für die Entwicklung einegstellt werden, sollten kommen ausschließlich eigene Programmierer zum Einsatz. Der Fokus liegt dabei auf einer schnellen und kostengünstigen Programmierung des Projektes. Dies äußert sich in einer schlechten Code Qualität, d.h. praktisch, wenn ein anderer Programmierer später etwas ändern soll, dann dauert das Ewigkeiten, da der Code so schlecht ist, dass man nicht durchsieht. Guter Code ist vor allem gut lesbar und verständlich, wozu es erfahrene Programmierer benötigt, denen auch Zeit dafür eingeräumt wird guten Code zu schreiben.

Bei Agenturen wird der Programmierer nicht angehalten guten Code zu schreiben und oft entscheiden man sich als Freelancer nur “im Ausnahmefall” bei einer Agentur zu arbeiten, weil dies meist mit vielen Überstunden, Zeitdruck und schlechter Bezahlung einher geht. Deswegen landen nicht die guten Programmierer bei Agenturen, sondern eher die schwarzen Schafe.

Meine Empfehlung ist, nicht auf eine Agentur zu setzen bei der Entwicklung von Software, sondern lieber auf einen oder mehrer gute Freelancer, der das Projekt gewissenhaft und in direkter Kommunikation umsetzt.

Beim Vergleich von Angeboten von verschiedenen Freelancern sollte nicht nur auf den Preis, sondern auch auf die Erfahrung des Programmierers und Qualität der dadurch entstehenden Software ein Augenmerk gelegt werden.

Meine Gedanken darüber habe ich aus meinen und den Erfahrungen von anderen Freelancern über die Jahre in Berlin gesammelt.

]]>
http://www.sebastianviereck.de/warum-man-software-projekte-nicht-bei-agenturen-entwicklen-lassen-sollte/feed/ 0
Verabreiten großer Dateien in PHP mittels Generator http://www.sebastianviereck.de/verabreiten-grosser-dateien-mit-php-mittels-generator/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=verabreiten-grosser-dateien-mit-php-mittels-generator http://www.sebastianviereck.de/verabreiten-grosser-dateien-mit-php-mittels-generator/#comments Sat, 25 Feb 2017 10:33:44 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3207-de Weiterlesen ]]> Um große Datenmengen mit PHP zu verarbeiten benötigt man viel Memory Speicher, weil große Mengen Daten geladen und dann verarbeitet werden. Eine speichersparende Alternative bieten Generatoren ab PHP 5.5., die mit dem yield Befehl durch große Datenmengen iterieren können und nur Speicherplatz für einen Datensatz belegen.

Beispiel: Verarbeiten einer großen CSV Datei mittels Generators:

<?php
class CsvFile {

    protected $file;

    public function __construct($file) {
        $this->file = fopen($file, 'r');
    }

    public function parse() {
        while (!feof($this->file)) {
            yield fgetcsv($this->file);
        }
        return;
    }
}

$csv = new CsvFile('/pathTo/file.csv');
foreach ($csv->parse() as $row) {
    echo $row;
}
]]>
http://www.sebastianviereck.de/verabreiten-grosser-dateien-mit-php-mittels-generator/feed/ 0
Vergleich: Bücher verkaufen bei Momox und Rebuy http://www.sebastianviereck.de/vergleich-buecher-verkaufen-bei-momox-und-rebuy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=vergleich-buecher-verkaufen-bei-momox-und-rebuy http://www.sebastianviereck.de/vergleich-buecher-verkaufen-bei-momox-und-rebuy/#comments Sun, 19 Feb 2017 15:13:56 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3196-de Weiterlesen ]]> Ich habe heute alles ausgemistet und meine seit Jahren nicht mehr angefassten programmierbücher versucht zu verkaufen bei momox.de und rebuy.de.

Dazu habe ich mir die App des jeweiligen Anbieters heruntergeladen und meine Bücher eingescannt. Man erhält sofort einen Preis und kann entscheiden, ob man das Buch/CD/DVD verkaufen will. Wenn man mindestens 10€ zusammen hat, kann man den Verkauf abschließen und bekommt kostenlos einen Packetgutschein für Post oder DHL und schickt dann sein Packet an den Anbieter. Der schaut sich die Artikel an und den Zustand und überweist dann das Geld.

Vorteil von momox

Die App ist besser, der Barcodescanner genauer zu händeln und übersichtlicher/intuitiver zu bedienen.

Über die App kann man auch DHL Versand auswählen (rebuy hat zwar auch DHL im Angebot, aber die App bietet nur Hermes an).

Man erhält 5€ mit dem Rabatcoupon (bei mir war es momox16 oder bald momox17, mal schauen).

Momox nervt einen auch weniger mit Marketing für den Verkauf von ihren Artikeln.

Rebuy überweist das Geld nicht direkt auf das Konto, sondern schreibt einem erstmal ein “Guthaben” in Ihrem Shop gut, damit man dort einkaufen geht. Um das Geld auf das Konto zu bekommen muss man noch extra tätig werden.

Vorteile von rebuy

Man muss weniger Daten eintippen auf der App, ich musste allerdings nicht mal initial meine Bankdaten eingeben, was ich komisch finde, aber mal sehen.

Zwischenstand

Jetzt gerade sind beide Pakete auf dem Weg mit der DHL zu den Anbietern, ich hoffe es verläuft alles reibungslos.

Ich fand es ganz interessant, bei beiden zu verkaufen, weil der eine oft mehr zahlt als der andere, man kann so gut die Preise vergleichen und sich den besten raussuchen.

Ergebnis

Sowohl Rebuy und Momox haben mir nach nur einer Woche das volle Geld überwiesen ohne Probleme mit der Ware.

Deswegen lautet meine Empfehlung: Momox

]]>
http://www.sebastianviereck.de/vergleich-buecher-verkaufen-bei-momox-und-rebuy/feed/ 1
MySQL Monitoriong der ProcessList / Queries mit einem Konsolen Befehl http://www.sebastianviereck.de/mysql-monitoriong-der-processlist-queries-mit-einm-konsolen-befehl/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mysql-monitoriong-der-processlist-queries-mit-einm-konsolen-befehl http://www.sebastianviereck.de/mysql-monitoriong-der-processlist-queries-mit-einm-konsolen-befehl/#comments Wed, 15 Feb 2017 09:26:12 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3190-de Weiterlesen ]]> Ein hilreicher Befehl für die problem-Analyse von MySQL Servern ist sich die ProcessList anzuschauen, um zu sehen, welche Quueries aktuell ausgeführt werden. Wenn man dies kombiniert mit dem watch Befehl und diesen 1 mal pro Sekunde neuladen lässt und auf die Queries reduziert, hat man eine guter Übersicht, was auf dem MySQL Server los ist und welche Queries problematisch seien könnten:

watch -n 1 "mysql -u root --password='XXX' -h localhost -s -e 'SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE Command=\"Query\";'"

Wichtig ist, den Befehl als root laufen zu lassen, um auch alle Queries zu sehen.

Mit Hilfe des Parameter -n kann man die Aktualisierungrate in Sekunden angeben.

Das MySQL root-Passwort ist zu ergänzen.

 

Ausgabe:

5361925476      user     localhost       NULL    Query   0       executing       SELECT * FROM xxx WHERE yyy

5361925477      user     localhost       NULL    Query   0       executing       UPDATE zzz WHERE zzz
]]>
http://www.sebastianviereck.de/mysql-monitoriong-der-processlist-queries-mit-einm-konsolen-befehl/feed/ 0
WordPress Posts mit Links autoamtisch als Spam markieren http://www.sebastianviereck.de/wordpress-posts-mit-links-autoamtisch-als-spam-markieren/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wordpress-posts-mit-links-autoamtisch-als-spam-markieren http://www.sebastianviereck.de/wordpress-posts-mit-links-autoamtisch-als-spam-markieren/#comments Sun, 12 Feb 2017 09:27:14 +0000 Sebastian Viereck http://www.sebastianviereck.de/?p=3181-de Weiterlesen ]]> Damit man von dn ganzen Spam Bots nicht genervt wird, deren Zie es immer ist einen Kommentar mit einem oder mehreren Links auf ener Webseite zu platzieren, habe ich ein kurzes Skript geschrieben, was in die function.php eingefügt werden muss. Das Skript markiert alle Kommentare als Spam, die einen Link enthalten.

add_action( 'comment_post', 'show_message_function', 10, 2 );
function show_message_function( $comment_ID, $comment_approved ) {
   $comment = get_comment( $comment_ID);
   if(!empty($comment)){
      $content = $comment->comment_content;
      if(!empty($content)){
         $content = strtolower($content);
         $hasLink = strpos($content, 'http') !== false || strpos($content, 'www.') !== false || strpos($content, 'href') !== false;
         if($hasLink){
            //when has link, set to spam
            $commentarr = array();
            $commentarr['comment_ID'] = $comment_ID;
            $commentarr['comment_approved'] = 'spam';
            wp_update_comment( $commentarr );
         }
      }

   }

}
]]>
http://www.sebastianviereck.de/wordpress-posts-mit-links-autoamtisch-als-spam-markieren/feed/ 0