Много материалов перечитал и просмотрел!
в Yii2 сложно привести код к имеющимся стандартам малой кровью!
при всех обсуждениях пришли к тому что нам на данный момент важны несколько вещей:
1) стабильность проекта
2) тесты
3) понятный код
4) скорость выполнения работ
5) стоимость изменений
немного о некоторых пунктах и их значимостью:
1) стабильность проект - по идее это понятие очень зависит от тестов и тесты должны быть на первом месте но у нас много мест уже и так стабильных и на них нет тестов и переписывать в ближайшее время мы не собираемся!
2) понятный код и скорость выполнения работ - мы решили что понятный код нам важнее чем скорость выполнения так как в будущем это сильно влияет как на скорость разработки так и на стоимость
и так чтоб не терять в скорости работы мы решили что мы реализуем только сервисный слой который обнесём тестами!
отсюда следует что в AR не должно быть бизнес логики - фактически это дто с валидацией и связью с бд
сервисы мы реализуем 2 способами
1) когда сервис это модуль
2) классический вариант
немного кода
тест реферального модуля
Код: Выделить всё
<?php
use app\models\User;
class ReferralTest extends \Codeception\Test\Unit
{
public function getReferalModule(): \app\modules\referral\Module
{
return Yii::$app->getModule('referral');
}
public function testApplyReferal()
{
$referralUser = User::find()->one();
$buyerUser = User::find()
->where(['!=', 'id', $referralUser->id])
->andWhere(['referral_user_id' => null])
->one();
$this->getReferalModule()->setCurrentReferralUserID($referralUser->id);
$this->assertTrue($this->getReferalModule()->applyReferralUser($buyerUser));
$this->assertEquals($referralUser->id, $buyerUser->referral_user_id);
}
public function testApplyReferalToUserWithReferal()
{
$buyerUser = User::find()
->andWhere(['>', 'referral_user_id', 0])
->one();
$referralUser = User::find()
->where(['!=', 'id', $buyerUser->id])
->andWhere(['!=', 'id', $buyerUser->referral_user_id])
->one();
$this->getReferalModule()->setCurrentReferralUserID($referralUser->id);
$this->assertTrue($this->getReferalModule()->applyReferralUser($buyerUser));
$this->assertNotEquals($referralUser->id, $buyerUser->referral_user_id);
}
}
Код: Выделить всё
<?php
use app\models\User;
use Yii;
class CouponTest extends \Codeception\Test\Unit
{
public function testMaxPriceExceeds()
{
$course = new \app\models\Courses([
'price_1_new' => 10,
'price_2_new' => 20,
'price_3_new' => 30,
]);
$coupon = new \app\models\Promocodes([
'maxprice' => 15
]);
$basketService = Yii::createObject(\app\components\services\interfaces\BasketServiceInterface::class);
$basketService->clear();
$basketService->setItem($course->getPrice(2), 1);
try {
$basketService->applyCoupon($coupon);
$this->assertFalse(true);
} catch (Exception $exception) {
$this->assertFalse(!($exception instanceof \app\components\services\exceptions\CouponMaxPriceException), $exception->getMessage());
}
}
public function testMaxPricePasses()
{
$course = new \app\models\Courses([
'price_1_new' => 10,
'price_2_new' => 20,
'price_3_new' => 30,
]);
$coupon = new \app\models\Promocodes([
'maxprice' => 15
]);
$basketService = Yii::createObject(\app\components\services\interfaces\BasketServiceInterface::class);
$basketService->clear();
$basketService->setItem($course->getPrice(1), 1);
try {
$basketService->applyCoupon($coupon);
$this->assertTrue(true);
} catch (Exception $exception) {
$this->assertTrue(false, $exception->getMessage());
}
}
}
также нам понравилось писать в начале тесты
создавая интерфейс сервиса и только потом создавать рабочий вариант (меньше вопросов что должно получится, многие стали смотреть в тесты как на вспомогательный материал к заданию)
по итогу скорость работы фактически не пострадала
бизнес логика постепенно переходит в сервисный слой и обносится тестами
в данный момент это наш баланс разумного подхода к нашим проектам!