Add tests for Support classes

This commit is contained in:
Christopher C. Wells 2021-03-28 09:18:30 -07:00 committed by Christopher Charbonneau Wells
parent d69d962287
commit 01b414c22c
9 changed files with 285 additions and 94 deletions

View File

@ -71,12 +71,6 @@ class Nutrients
/**
* Calculate a nutrient multiplier for a Food.
*
* @param \App\Models\Food $food
* @param float $amount
* @param string|null $fromUnit
*
* @return float
*/
public static function calculateFoodNutrientMultiplier(
Food $food,
@ -93,6 +87,7 @@ class Nutrients
return $amount / $food->serving_weight;
}
// @todo Determine if `empty($food->serving_unit)` case makes sense.
if (
empty($fromUnit)
|| empty($food->serving_unit)
@ -130,13 +125,6 @@ class Nutrients
/**
* Calculate a nutrient amount for a recipe.
*
* @param \App\Models\Recipe $recipe
* @param string $nutrient
* @param float $amount
* @param string $fromUnit
*
* @return float
*/
public static function calculateRecipeNutrientAmount(
Recipe $recipe,

View File

@ -8,21 +8,81 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class FoodFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
* {@inheritdoc}
*/
protected $model = Food::class;
/**
* Define the model's default state.
*
* @return array
* {@inheritdoc}
*/
public function definition()
public function definition(): array
{
return [
//
'name' => $this->faker->word,
'detail' => $this->faker->sentence(2),
'brand' => $this->faker->word,
'source' => $this->faker->url,
'serving_size' => $this->faker->randomFloat(2, 1/2, 5),
'serving_unit' => $this->faker->randomElement(['tsp', 'tbsp', 'cup']),
'serving_weight' => $this->faker->numberBetween(5, 500),
'calories' => $this->faker->randomFloat(2, 0, 100),
'fat' => $this->faker->randomFloat(2, 0, 10),
'cholesterol' => $this->faker->randomFloat(2, 0, 100),
'sodium' => $this->faker->randomFloat(2, 0, 500),
'carbohydrates' => $this->faker->randomFloat(2, 0, 20),
'protein' => $this->faker->randomFloat(2, 0, 20),
];
}
/**
* Make instance with "tsp" serving unit.
*/
public function tspServingUnit()
{
return $this->state(function (array $attributes) {
return [
'serving_unit' => 'tsp',
'serving_size' => 1,
];
});
}
/**
* Make instance with "tbsp" serving unit.
*/
public function tbspServingUnit()
{
return $this->state(function (array $attributes) {
return [
'serving_unit' => 'tbsp',
'serving_size' => 1,
];
});
}
/**
* Make instance with "cup" serving unit.
*/
public function cupServingUnit()
{
return $this->state(function (array $attributes) {
return [
'serving_unit' => 'cup',
'serving_size' => 1,
];
});
}
/**
* Make instance with no" serving unit.
*/
public function noServingUnit()
{
return $this->state(function (array $attributes) {
return [
'serving_unit' => null,
'serving_unit_name' => 'head'
];
});
}
}

View File

@ -21,8 +21,8 @@
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>

View File

@ -1,21 +0,0 @@
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testBasicTest()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}

View File

@ -1,32 +0,0 @@
<?php
namespace Tests\Feature;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class RegistrationTest extends TestCase
{
use RefreshDatabase;
public function test_registration_screen_can_be_rendered()
{
$response = $this->get('/register');
$response->assertStatus(200);
}
public function test_new_users_can_register()
{
$response = $this->post('/register', [
'name' => 'Test User',
'email' => 'test@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
}
}

View File

@ -0,0 +1,104 @@
<?php
namespace Tests\Feature\Support;
use App\Models\Food;
use App\Support\Nutrients;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class NutrientsTest extends TestCase
{
use RefreshDatabase;
/**
* Test invalid Food nutrient multiplier calculation.
*
* @dataProvider foodsInvalidNutrientMultipliersProvider
*/
public function testCalculateFoodInvalidNutrientMultiplier(
Food $food,
float $amount,
string $fromUnit,
): void {
$this->expectException(\DomainException::class);
Nutrients::calculateFoodNutrientMultiplier($food, $amount, $fromUnit);
}
/**
* Test valid Food nutrient multiplier calculation.
*
* @dataProvider foodsValidNutrientMultipliersProvider
*/
public function testCalculateFoodValidNutrientMultiplier(
Food $food,
float $amount,
string $fromUnit,
float $expectedMultiplier
): void {
$this->assertEquals(
Nutrients::calculateFoodNutrientMultiplier($food, $amount, $fromUnit),
$expectedMultiplier
);
}
/**
* Data providers.
*/
/**
* Provide example foods and expected nutrient multipliers.
*/
public function foodsInvalidNutrientMultipliersProvider(): array {
$this->refreshApplication();
/** @var \App\Models\Food $foodInvalidUnit */
$foodInvalidUnit = Food::factory()->make(['serving_unit' => 'invalid']);
return [
[$foodInvalidUnit, 1, 'tsp'],
[$foodInvalidUnit, 1, 'tbsp'],
[$foodInvalidUnit, 1, 'cup'],
[Food::factory()->tspServingUnit()->make(), 1, 'invalid'],
];
}
/**
* Provide example foods and expected nutrient multipliers.
*/
public function foodsValidNutrientMultipliersProvider(): array {
$this->refreshApplication();
/** @var \App\Models\Food[] $foods */
$foods = [
'tsp' => Food::factory()->tspServingUnit()->make(),
'tbsp' => Food::factory()->tbspServingUnit()->make(),
'cup' => Food::factory()->cupServingUnit()->make(),
'none' => Food::factory()->noServingUnit()->make(),
];
return [
[$foods['tsp'], $foods['tsp']->serving_weight, 'oz', Nutrients::$gramsPerOunce],
[$foods['tsp'], 1, 'serving', 1],
[$foods['tsp'], $foods['tsp']->serving_weight * 1.5, 'gram', 1.5],
[$foods['tsp'], 2, 'tsp', 2],
[$foods['tsp'], 1, 'tbsp', 3],
[$foods['tsp'], 1, 'cup', 48],
[$foods['tbsp'], $foods['tbsp']->serving_weight, 'oz', Nutrients::$gramsPerOunce],
[$foods['tbsp'], 1, 'serving', 1],
[$foods['tbsp'], $foods['tbsp']->serving_weight * 2, 'gram', 2],
[$foods['tbsp'], 2, 'tsp', 2/3],
[$foods['tbsp'], 1, 'tbsp', 1],
[$foods['tbsp'], 2, 'cup', 32],
[$foods['cup'], $foods['cup']->serving_weight, 'oz', Nutrients::$gramsPerOunce],
[$foods['cup'], 1, 'serving', 1],
[$foods['cup'], $foods['cup']->serving_weight * 2.25, 'gram', 2.25],
[$foods['cup'], 3, 'tsp', 1/16],
[$foods['cup'], 2, 'tbsp', 1/8],
[$foods['cup'], 5, 'cup', 5],
[$foods['none'], $foods['none']->serving_weight, 'oz', Nutrients::$gramsPerOunce],
[$foods['none'], 1, 'serving', 1],
[$foods['none'], $foods['none']->serving_weight * 3.0125, 'gram', 3.0125],
];
}
}

View File

@ -1,18 +0,0 @@
<?php
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testBasicTest()
{
$this->assertTrue(true);
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace Tests\Unit\Support;
use App\Support\ArrayFormat;
use PHPUnit\Framework\TestCase;
class ArrayFormatTest extends TestCase
{
/**
* Test input array "flipping".
*
* @see \App\Support\ArrayFormat::flipTwoDimensionalKeys()
*/
public function testFlipTwoDimensionalKeys(): void
{
$input = [
'ingredient' => [
0 => 'ingredient-0',
1 => 'ingredient-1',
2 => 'ingredient-2',
3 => 'ingredient-3',
],
'amount' => [
0 => 'amount-0',
1 => 'amount-1',
2 => 'amount-2',
3 => 'amount-3',
],
];
$expected = [
['ingredient' => 'ingredient-0', 'amount' => 'amount-0'],
['ingredient' => 'ingredient-1', 'amount' => 'amount-1'],
['ingredient' => 'ingredient-2', 'amount' => 'amount-2'],
['ingredient' => 'ingredient-3', 'amount' => 'amount-3'],
];
$this->assertEqualsCanonicalizing($expected, ArrayFormat::flipTwoDimensionalKeys($input));
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace Tests\Unit\Support;
use App\Support\Number;
use PHPUnit\Framework\TestCase;
class NumberTest extends TestCase
{
/**
* Test float to string conversion.
*
* @dataProvider decimalStringFloatsProvider
* @dataProvider fractionStringFloatsProvider
*
* @see \App\Support\Number::floatFromString()
*/
public function testFloatFromString(string $string, float $expectedFloat): void
{
$result = Number::floatFromString($string);
$this->assertIsFloat($result);
$this->assertEquals($expectedFloat, $result);
}
/**
* Test (fraction) string to float conversion.
*
* @dataProvider fractionStringFloatsProvider
*
* @see \App\Support\Number::fractionStringFromFloat()
*/
public function testFractionStringFromFloat(string $expectedString, float $float): void
{
$result = Number::fractionStringFromFloat($float);
$this->assertIsString($result);
$this->assertEquals($expectedString, $result);
}
/**
* Data providers.
*/
/**
* Provide decimal string and float data.
*
* @see \Tests\Unit\Support\NumberTest::testFloatFromString()
*/
public function decimalStringFloatsProvider(): array {
return [
['0.0', 0.0], ['0.125', 1/8], ['0.25', 1/4], ['0.5', 1/2],
['0.75', 3/4], ['1.0', 1.0], ['1.25', 1.25], ['1.5', 1.5],
['2.5', 2.5], ['2.75', 2.75],
];
}
/**
* Provide fraction string and float data.
*
* @see \Tests\Unit\Support\NumberTest::testFloatFromString()
* @see \Tests\Unit\Support\NumberTest::testFractionStringFromFloat()
*/
public function fractionStringFloatsProvider(): array {
return [
['0', 0.0], ['1/8', 1/8], ['1/4', 1/4], ['1/3', 1/3], ['1/2', 1/2],
['2/3', 2/3], ['3/4', 3/4], ['1', 1.0], ['1 1/4', 1.25],
['1 1/2', 1.5], ['2 1/2', 2.5], ['2 3/4', 2.75],
];
}
}