I denna labb ska vi titta närmare på hur vi kan testa PHP-kod och refaktorisera den samma.
Vi kommer att utgå från ett existerande Composerprojekt (Johans förolämpningstjänst) och skriva tester för det. Vi kommer också att refaktorisera koden.
Curl är ett bibliotek som används för att anropa HTTP-servrar. Det används av Composer-biblioteket Guzzle.
Om du kör XAMPP enligt Antons anvisningar, följer du den här guiden.
Om du kör XAMPP enligt Antons anvisningar, [följer du den här guiden](https://danieldrave.co.uk/enabling-ssl-and-curl-on-xampp/.
Öppna en terminal och skriv in
$ sudo apt-get install php-curl
- Klona det befintliga projektet.
- Initalisera Composer och GitFlow.
- Testa koden.
- Refaktorisera koden.
Vi är intresserade av Johans gamla demoprojekt på https://github.com/koddas/php-web-application. Klona det genom att skriva
$ git clone https://github.com/koddas/php-web-application
Installera projektets beroenden med hjälp av Composer:
$ composer install
Säkerställ att projektet körs ordentligt genom att gå in i katalogen php-web-application/src/ och starta utvecklingsservern:
$ cd php-web-application/src/
$ php -S localhost:8000
Gå sedan in på http://localhost:8000 och se om du ser en webbsida.
Vi kommer att använda oss av GitFlow för att skapa en branch för att skriva enhetstester. Gör detta genom att skriva följande i teminalen:
$ cd ..
$ git flow init -d
Gå igenom guiden som vanligt (se Laboration 4). Notera gärna att src/vendor redan ligger i .gitinit.
Vår kod fungerar, vad vi kan se. Vi kan inte vara säkra på hur väl det faktiskt fungerar, dock.
Skapa en feature-branch för testskrivandet genom att skriva
$ git flow feature start unit_tests
Vi behöver lägga till PHPUnit (se https://phpunit.de) till vårt projekt för att kunna skriva våra tester. Detta ska göras till våra utvecklingsberoenden (require-dev):
$ composer require --dev
Sök efter phpunit och välj sedan alternativet phpunit/phpunit.
Nästa steg är att sätta upp PHPUnits testmiljö. Verktyget har en föredragen fil- och katalogstruktur som vi måste följa. PHPUnit föredrar när våra tester ligger i katalogen tests/, så vi skapar en sådan:
$ mkdir tests
I vår projektrot skapar vi sedan konfigurationsfilen phpunit.xml med följande innehåll:
<phpunit bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="Tests">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
Skapa sedan filen tests/bootstrap.php med följande innehåll:
<?php
require dirname(__DIR__) . '/vendor/autoload.php';
Vi börjar så smått med att skriva ett enkelt test. Vi vill testa att hämta ett namn med hjälp av metoden get_name() i klassen Utils. Vi skapar därför en fil tests/UtilsTest.php med följande innehåll:
<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
require dirname(__DIR__) . '/src/Utils.php';
final class UtilsTest extends TestCase
{
public function testGetNameWithValidValue()
{
$utils = new Utils();
$this->assertEquals("Axel", $utils->get_name(1981, 6, 16));
}
}
Den här filen är på intet sätt fullständig, men duger bra för tillfället.
Testsviten kör du genom att skriva följande i terminalen:
$ vendor/bin/phpunit -c phpunit.xml
Om utskriften ser ut som nedan har ditt testfall gått igenom:
Det är viktigt att testa inte bara det som uppenbart fungerar, utan även gränsfall och saker som inte ska fungera. Det här blir en övning för dig att göra. Skriv ett antal relevanta testfall för varje metod i Utils. Exempel på saker som du kan testa för get_name är:
- Negativa årtal
- Den första och sista dagen i varje månad
- Månad 13
- Månadsnamn istället för två siffror
- Månad eller dag med bara en siffra
- Skicka med en array eller boolean som indata
Förhoppningsvis har du nu stött på en massa fel i koden. Om inte, gå tillbaka och skriv fler tester. Det finns många skavanker i koden.
Din uppgift är nu att åtgärda felen på ett sätt så att alla dina testfall går igenom. Notera gärna att en fix som löser ett testfall kan resultera i att ett annat testfall inte längre går igenom.
När du är färdig, mergea in din test-branch genom att i terminalen skriva:
$ git flow feature finish unit_tests
Du har säkert varit med om att du öppnat upp gammal kod som du själv skrivit och konstaterat att det inte varit någon vacker läsning. Programmet kanske fungerar, men koden ger en dålig smak i munnen. Du har just varit med om code smell, vilket är en magkänsla som förknippas med kod som är mindre bra.
Koden har, trots sin numera klanderfria funktion, fortfarande små skavanker. Exempelvis har den metodnamn som använder snake_case istället för camelCase. Åtgärda detta och se till så att testfallen fortfarande går igenom. När du är klar, se om du kan hitta några fler fall av code smell och åtgärda dem.
Öppna upp tidigare laborationsuppgifter och refaktorisera dem. Vilka typer av code smell hittar du i dem? Hur fixar du dem? Diskutera med en kursare.