feat: Semaine 13
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
class Facture
|
||||
{
|
||||
private array $lignes = [];
|
||||
|
||||
public function ajouterLigne(
|
||||
string $libelle,
|
||||
float $prixHT,
|
||||
int $qte
|
||||
): void
|
||||
{
|
||||
$this->lignes[] = [
|
||||
'libelle' => $libelle,
|
||||
'prixHT' => $prixHT,
|
||||
'qte' => $qte,
|
||||
];
|
||||
}
|
||||
|
||||
public function totalHT(): float
|
||||
{
|
||||
$total = 0;
|
||||
foreach ($this->lignes as $l) {
|
||||
$total += $l['prixHT'] * $l['qte'];
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
}
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FactureTest extends TestCase
|
||||
{
|
||||
public function testTotalHTDeDeuxLignes()
|
||||
{
|
||||
// 1. ARRANGE
|
||||
$facture = new Facture();
|
||||
|
||||
// 2. ACT
|
||||
$facture->ajouterLigne("Exemple de ligne 1", 150.0, 3);
|
||||
$facture->ajouterLigne("Exemple de ligne 2", 49.99, 10);
|
||||
|
||||
// 3. ASSERT
|
||||
$this->assertEqualsWithDelta(949.9, $facture->totalHT(), 0.0001);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,56 @@
|
||||
# Exercice 03 - Adam, Louis, Gauvain
|
||||
|
||||
## Ecrire son premier test
|
||||
|
||||
### Class Facture
|
||||
|
||||
```php
|
||||
<?php
|
||||
class Facture
|
||||
{
|
||||
private array $lignes = [];
|
||||
|
||||
public function ajouterLigne(
|
||||
string $libelle,
|
||||
float $prixHT,
|
||||
int $qte
|
||||
): void
|
||||
{
|
||||
$this->lignes[] = [
|
||||
'libelle' => $libelle,
|
||||
'prixHT' => $prixHT,
|
||||
'qte' => $qte,
|
||||
];
|
||||
}
|
||||
|
||||
public function totalHT(): float
|
||||
{
|
||||
$total = 0;
|
||||
foreach ($this->lignes as $l) {
|
||||
$total += $l['prixHT'] * $l['qte'];
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```php
|
||||
<?php
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FactureTest extends TestCase
|
||||
{
|
||||
public function testTotalHTDeDeuxLignes()
|
||||
{
|
||||
// 1. PREPARER
|
||||
$facture = new Facture();
|
||||
|
||||
// 2. AGIR
|
||||
$facture->ajouterLigne("Exemple de ligne 1", 150.0, 3);
|
||||
$facture->ajouterLigne("Exemple de ligne 2", 49.99, 10);
|
||||
|
||||
// 3. VERIFIER
|
||||
$this->assertEqualsWithDelta(949.9, $facture->totalHT(), 0.0001);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,101 @@
|
||||
# Exercice 04 - Adam Louis Gauvain
|
||||
|
||||
## Chasse au bogue - 3 pièges dans 20 lignes
|
||||
|
||||
```php
|
||||
public function appliquerRemise(float $pourcent): void
|
||||
{
|
||||
foreach ($this->lignes as $i => $ligne) {
|
||||
$this->lignes[$i]["prixHT"] *= (1 - $pourcent / 100);
|
||||
}
|
||||
}
|
||||
|
||||
public function totalTTC(float $tauxTVA): float
|
||||
{
|
||||
return $this->totalHT() * (1 + $tauxTVA);
|
||||
}
|
||||
|
||||
public function estPayee(): bool
|
||||
{
|
||||
return $this->montantRegle == $this->totalTTC(0.20);
|
||||
}
|
||||
```
|
||||
|
||||
## Réponses
|
||||
|
||||
### Cas 1
|
||||
|
||||
```php
|
||||
public function appliquerRemise(float $pourcent): void
|
||||
{
|
||||
foreach ($this->lignes as $i => $ligne) {
|
||||
$this->lignes[$i]["prixHT"] *= (1 - $pourcent / 100);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```php
|
||||
appliquerRemise(15.5) // Cas réaliste
|
||||
// ligne 1 : prix 100 (remise : 15,5, total 84,5)
|
||||
// ligne 2 : prix 200 (remise : 31, total 169)
|
||||
|
||||
// Renvoi lignes
|
||||
lignes[i] = $prixHT * (1 - 15.5 / 100) // 100 * 0,845
|
||||
```
|
||||
|
||||
```php
|
||||
appliquerRemise(150) // Cas irréaliste
|
||||
// ligne 1 : prix 100 (remise : 150, total -50)
|
||||
// ligne 2 : prix 200 (remise : 300, total -100)
|
||||
|
||||
// Renvoi lignes
|
||||
lignes[i] = $prixHT * (1 - 150 / 100) // 100 * -0.5, soit -50
|
||||
```
|
||||
|
||||
> Il faut appliquer une limite à 0€ minimum sur le site marchand, pour éviter que le total soit négatif.
|
||||
> SAUF si le marchand gère les avoirs, auquel cas, il faut étendre la logique métier, et gérer les résultats négatifs comme avoirs sur le compte client, et pas sur la commande.
|
||||
|
||||
### Cas 2
|
||||
|
||||
> 0.1 + 0.2 en PHP m'ont rendu 0.3, mais on connaît la possibilité d'avoir 0.300000000004 par exemple. Auquel cas, la logique métier voudrait un arrondi à deux décimales :
|
||||
|
||||
```php
|
||||
// https://www.php.net/number_format
|
||||
number_format($totalTTC, 2)
|
||||
```
|
||||
|
||||
> Sachant qu'un paradigme peu répandu mais loin d'être appliqué veut que l'adaptation à ce problème inhérent au binaire pour les virgules flottantes veut qu'on ne calcule QUE des nombres entiers (INT) en comptant à partir des centimes. Autrement dit, on ne calcule pas 100€ comme 100.00 en FLOAT mais comme 10000 centimes en INT.
|
||||
|
||||
### Cas 3
|
||||
|
||||
```php
|
||||
public function totalTTC(float $tauxTVA): float
|
||||
{
|
||||
return $this->totalHT() * (1 + $tauxTVA);
|
||||
}
|
||||
|
||||
public function estPayee(): bool
|
||||
{
|
||||
return $this->montantRegle == $this->totalTTC(0.20);
|
||||
}
|
||||
```
|
||||
|
||||
> La TVA peut être de 20% ou de 5,5% en France, et d'un taux différent dans d'autres pays. De fait, la validation de la TVA doit se faire selon un certains nombres de critères à valider dans une fonction, voire une classe dédiée.
|
||||
> Une logique métier serait un dictionnaire emboîté, avec les pays et les taux déclarés :
|
||||
|
||||
```json
|
||||
{
|
||||
"France": {
|
||||
"Particulier": 2.1,
|
||||
"Réduit": 5.5,
|
||||
"Intermédiaire": 10.0,
|
||||
"Normal": 20.0
|
||||
},
|
||||
"Belgique": {
|
||||
"Zéro": 0.0,
|
||||
"Réduit1": 6.0,
|
||||
"Réduit2": 12.0,
|
||||
"Normal": 21.0
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,67 @@
|
||||
# Exercice 05 - Adam, Louis, Gauvain
|
||||
|
||||
## Le test capricieux
|
||||
|
||||
```php
|
||||
public function testDateDeCreation()
|
||||
{
|
||||
$f = new Facture()
|
||||
$this->assertEquals(date("Y-m-d H:i:s"), $f->getDateCreation());
|
||||
}
|
||||
|
||||
public function testListeDesClients()
|
||||
{
|
||||
$clients = $this->db->query("SELECT * FROM clients");
|
||||
$this->assertCount(3, $clients);
|
||||
}
|
||||
```
|
||||
|
||||
### Test 1
|
||||
|
||||
```php
|
||||
public function testDateDeCreation()
|
||||
{
|
||||
// 1.
|
||||
// Définir un fuseau horaire précis pour éviter la confusion entre des pods d'un déploiement multi-régions
|
||||
// date_default_timezone_set('Europe/Paris');
|
||||
|
||||
$f = new Facture()
|
||||
|
||||
// 2.
|
||||
// Pourquoi comparer la date de création avec le moment T de ce code ?
|
||||
|
||||
// 3.
|
||||
// Il se peut qu'un décalage soit fait entre le temps de getDateCreation() et date("etc etc")
|
||||
// Il suffit que le processeur rame un peu, ou que l'instruction chevauche une seconde sur le fin et
|
||||
// on compare 15:03:02 à 15:03:03.
|
||||
// On pourrait alors mettre un assertEqualsWithDelta() et récupérer les dates en EPOCH pour ne
|
||||
// pas comparer des strings mais un INT.
|
||||
|
||||
$this->assertEquals(date("Y-m-d H:i:s"), $f->getDateCreation());
|
||||
}
|
||||
```
|
||||
|
||||
### Test 2
|
||||
|
||||
```php
|
||||
public function testListeDesClients()
|
||||
{
|
||||
// 1.
|
||||
// Où est géré la connexion ? Est-on sûrs qu'elle est établie ?
|
||||
// Y a-t-il un équivalent de 'try: except:' en PHP ?
|
||||
|
||||
// 2.
|
||||
// Est-ce qu'il y a une gestion d'exception dans le cas où la table
|
||||
// 'clients' n'est pas créée ?
|
||||
|
||||
$clients = $this->db->query("SELECT * FROM clients");
|
||||
|
||||
// 3.
|
||||
// Pourquoi 3 ? N'a-t-on que 3 clients ? Il vaut mieux vérifier un "supérieur à 0"
|
||||
// mais vouloir ne garder que 3 clients, c'est ridicule. Sauf si on veut chercher des
|
||||
// clients spéciaux (mettons des clients Grands Comptes), auquel cas on va plutôt
|
||||
// récupérer une valeur dynamique en première phase de l'assertion
|
||||
|
||||
$this->assertCount(3, $clients);
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user