3

Я добавляю тесты к проекту Symfony2. Раньше я использовал ту же базу данных для окружения dev и test, она использовала базу данных MySQL, уже заполненную теми же данными, что и на производственном сервере.Независимые функциональные тесты с LiipFunctionalTestBundle и светильники?

Тесты работали зависимо, потому что некоторые тесты зависели от предыдущих тестов. Например, если у меня был сайт магазина, я добавил продукт в корзину и удалил продукт из корзины. Поэтому мне нужно было вставить данные, используя форму, прежде чем удалять ее.

Теперь я хочу работать с независимыми функциональными тестами, потому что это recommended way (by one of Symfony2's developers).

Я правильно настроил LiipFunctionalTestBundle базу данных SQLite в среде test, и я начал добавлять светильники с DoctrineFixturesBundle.

Но я не знаю, сколько данных я должен загрузить для каждого функционального теста. Какой прибор следует загружать в начале теста? Как работать с CRUD-операциями, когда объект зависит от других объектов из-за связей между таблицами?

Скажем, я разрабатываю магазин, я хочу несколько тестов:

  1. Пользователя добавить некоторые продукты в своей корзине
  2. Пользователя удалить один продукт из корзины
  3. Порядок пользователя оставшиеся продукты

Должен ли я создать другое приспособление для каждого шага? Это означает, что мои светильники должны будут существовать во многих разных состояниях: пустая тележка, тележка с заказом одного продукта и т. Д. Это кажется мне правильным, но очень трудоемким, поэтому мне интересно, действительно ли моя идея действительна.

ответ

2

Для каждого тестового примера лучше как можно меньше нагружать приспособление как для изоляции, так и для работы (набор тестов может идти очень медленно).

Когда арматура зависит друг от друга, вы просто управляете ими с помощью ссылки на доктрину и связываете друг друга, также заботитесь о заказе. Как пример, предположим, просто отношения пользователя и роли.

Общий класс для управления роль арматуре:

abstract class BaseLoadRoleData extends AbstractFixture implements OrderedFixtureInterface 
{ 


    public function getOrder() 
    { 
     return 1; 
    } 

    protected function createRole(ObjectManager $manager, $rolename) 
    { 
     $role= new Role(); 
     $role->setName($rolename); 

     $manager->persist($role); 
     $manager->flush(); 
     $this->setReference('role-' . $rolename, $role); 
    } 
} 

Выделенный класс для простой роли

class LoadSimpleRoleData extends BaseLoadRoleData 
{ 
    public function load(ObjectManager $manager) 
    { 
     $this->createRole($manager, Role::SIMPLE); 
    } 
} 

Выделенный класс для администратора Роль

class LoadAdminRoleData extends BaseLoadRoleData 
{ 
    public function load(ObjectManager $manager) 
    { 
     $this->createRole($manager, Role::ADMIN); 
    } 

} 

и пользователем : Общий класс для управления пользовательским прибором:

abstract class BaseLoadUserData extends AbstractFixture implements OrderedFixtureInterface 
{ 

    /** 
    * @var ContainerInterface 
    */ 
    private $container; 

    /** 
    * {@inheritDoc} 
    */ 
    public function setContainer(ContainerInterface $container = null) 
    { 
     $this->container = $container; 
    } 

    public function getOrder() 
    { 
     return 2; 
    } 

    protected function buildUser($username, $firstName = "",$lastName ="") 
    { 
     $user= new User(); 
     $user->setUsername($username); 
     $user->setFirstName($firstName); 
     $user->setLastName($lastName); 

     return $user; 

    } 
} 

Выделенный класс для простого пользователя

class LoadSimpleUserData extends BaseLoadUserData { 

    /** 
    * Load data fixtures with the passed EntityManager 
    * 
    * @param Doctrine\Common\Persistence\ObjectManager $manager 
    */ 
    function load(ObjectManager $manager) 
    { 
     $user = $this->buildUser($manager, "[email protected]"); 
     $user->addRole($this->getReference('role-'.Role::SIMPLE)); 
     $manager->persist($user); 
     $manager->flush(); 
     $this->setReference('user-' . "[email protected]", $user); 

    } 
} 

Выделенный класс для администратора пользователя

class LoadAdminUserData extends BaseLoadUserData { 

    /** 
    * Load data fixtures with the passed EntityManager 
    * 
    * @param Doctrine\Common\Persistence\ObjectManager $manager 
    */ 
    function load(ObjectManager $manager) 
    { 
     $user = $this->buildUser($manager, "[email protected]"); 
     $user->addRole($this->getReference('role-'.Role::ADMIN)); 
     $manager->persist($user); 
     $manager->flush(); 
     $this->setReference('user-' . "[email protected]", $user); 

    } 

Теперь вы можете использовать его отдельно, в качестве примера, на основе функционального теста Liip Bundle:

class LoginControllerTest { 

    public function testAdminUserLogin() 
    { 
     $this->loadFixtures(array(
      'Acme\DemoBundle\DataFixtures\ORM\LoadAdminRoleData', 
      'Acme\DemoBundle\DataFixtures\ORM\LoadAdminUserData' 
     )); 

     // you can now run your functional tests with a populated database 
     $client = static::createClient(); 
     // ... 

     // test the login with admin credential 
    } 

    public function testSimpleUserLogin() 
    { 
     // add all your fixtures classes that implement 
     // Doctrine\Common\DataFixtures\FixtureInterface 
     $this->loadFixtures(array(
      'Acme\DemoBundle\DataFixtures\ORM\LoadSimpleRoleData', 
      'Acme\DemoBundle\DataFixtures\ORM\LoadSimpleUserData' 
     )); 

     // you can now run your functional tests with a populated database 
     $client = static::createClient(); 
     // ... 

     // test the login with simple user credential 

    } 

} 

Надеюсь, что эта помощь.

+0

Что делать, если я также хочу протестировать пользователей с именами 'john' и' bob'? –

+0

Напишите специальный класс приборов для john и загрузите его в выделенный тестовый класс – Matteo

+0

Должен ли я копировать и вставлять весь код из класса LoadSimpleUserData? Нет ли лучшего метода? –

Смежные вопросы