Symfony 4: how to load DataFixtures in a KernelTestCase - unit-testing

I got DataFixtures set up, that I can load via console into my test database.
$ php bin/console doctrine:fixtures:load --env=test -n
> purging database
> loading App\DataFixtures\PropertyFixtures
> loading App\DataFixtures\UserFixtures
> loading App\DataFixtures\UserPropertyFixtures
works like a chram
But I am lost how to load these fixtures automatically with my service unit tests, without having to run the command manually before testing. There has to be another way!
What I found so far is descriptions for testing with older versions of symfony or for testing Controllers. Who wants to test Controllers anyway, if you can avoid it?
The Liip\FunctionalTestBundle also seems to work only for WebTestCases at least I have seen no way to extend or replace the usual KernelTestCase.
So is there any way I can maybe run the command with the setUp() method of my test class?
Any link to a tutorial for symfony 4? Any example for a service? I cannot imagine, that I am the only person with that problem.

I got a solution and although it is not full of beauty and style here it is. More elegant alternatives are appreciated.
I extended my Kernel class found in Kernel.php with a class called AppKernel.
To activate it for tests and only those I changed my phpunit.xml file:
<php>
<ini name="error_reporting" value="-1" />
<env name="KERNEL_CLASS" value="App\AppKernel" />
So now only for tests this class is loaded.
In the AppKernel Class I extended the boot method as follows:
public function boot()
{
parent::boot();
$this->importDataFixtures();
}
/**
* Loads the tests data for DataFixtures when we start phpUnit.
*/
protected function importDataFixtures()
{
system('php /var/www/octopus/bin/console doctrine:fixtures:load --env=test -n');
}
So of course the call of the import via system is ugly, but it works. If somebody has a better idea, please let my know.

Related

Phpunit shows errors in random test cases while running all the tests together

I have made a number of test cases on PHPUnit for Browser testing of the website, all these tests pass when I run them individually , but when I try to run them as a group or using php artisan dusk command, some of them fail. The real problem is that whenever I run them together, error occurs in different test cases every time.
I searched it on the internet and found RefreshDatabase and DatabaseTransaction commands but I can't use them as it is not a suitable solution and also not allowed by my colleagues. Kindly let me know what I'm missing or what else I should add in order to run all the tests smoothly.
P.S.I want to run them together for Auto-deployment on servers (testing and then deploying the changes)
Below is an example test for clear understanding of the issue:
<?php
namespace Tests\Browser;
use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class AddUsrSegmentTest extends DuskTestCase
{
/**
* create a user segment
*
* #return void
* #group other
*/
public function testExample()
{
$this->browse(function (Browser $browser) {
$browser->loginAs(\App\Model\User::find(4567))
->visit('/home')
->clickLink('Create From Scratch')
->assertPathis('/bot/dashboard')
//first create a user datastore
->visit('/bot/datastore')
->assertSee('Create a Global/User Datastore')
->visit('/bot/datastore/create')
->assertSee('Custom Values')
->click('#showCustomInput')
->type('key','colorsss')
//->type('.bootstrap-tagsinput > input:nth-child(1)','apple')
//->keys('.bootstrap-tagsinput > input:nth-child(1)','mango', ['{enter}'])
->keys('.bootstrap-tagsinput > input:nth-child(1)','green', ['{enter}'],'mustard',['{enter}'],'blue',['{enter}'],'red',['{enter}'])
->click('.slider')
->assertSee('Add Datastore')
->click('button.btn:nth-child(1)')// add datastore button
->visit('/bot/datastore')
->assertSeeIn('#zero-config','colorsss')

How to config environment before running automated tests?

I need a good practice to deal with my issue.
The issue is: I need to run automatic tests against a site. The site has different configurations that completely change its design (on some pages). For example I can config 2 different pages of login. And I need to test them both.
First of all I must make sure that a correct test is run against a correct configuration. So before each test I need to change site's config. It is not good if I have a thousand of test.
So a solution that comes to my mind is to not reconfigure the site each time but do it once and run all the tests that are corresponding to this configuration. But this solution doesn't seems to me as an easy one to make.
For now what I did is: I created a method that is run once before all the other tests and in this method I configure the site to make config that are used in the majority of the tests. All the other tests for now change the config before execution and after execution they change it back. It's not good at all.
To do so I used NUnit3 SetUpFixture and OneTimeSetUp attributes:
/// <summary>
/// Runs once before all the test in order to config the environment
/// </summary>
[SetUpFixture]
public class ConfigTests
{
[OneTimeSetUp]
public void RunBeforeAnyTests()
{
IWebDriver driver = new ChromeDriver();
try
{
//Here I config the stie
CommonActions actions = new CommonActions(driver);
actions.SwitchOffCombinedPaymentPage();
driver.Dispose();
}
catch (Exception)
{
driver.Dispose();
}
}
}
What I thought after this is that I'll be able to send parameters to SetUpFixture but first of all it's impossible and second of all it won't resolve the problem as this feature will just be run twice and the tests will be run against the last configuration.
So guys, how to deal with a site testing that has a lot of configurations?
I'd use a test run parameter from the command-line (or in the .runsettings file if you are using the VS adapter) Your SetUpFixture can grab that parameter and do the initialization and any individual fixtures that need it can grab it as well.
See the --params option to nunit3-console and the TestContext.TestParameters property for accessing the values.
This answers your "first of all it's impossible" part. I didn't answer "second of all... " because I don't understand it. I'll add more if you can clarify.

Zend Framework 2 unit testing using CodeCeption

We are currently using CodeCeption to do some acceptance testing, but I would like to also add unit testing to the current setup.
Has anyone done Unit testing in Zend Framework 2 project using CodeCeption? And if so, how did you set up the environment?
Found this in codeception docs: http://codeception.com/docs/modules/ZF2
There is an example in this github project: https://github.com/Danielss89/zf2-codeception
I solved this problem by using PHPUnit. I followed the Zend PHPUnit guide, http://framework.zend.com/manual/current/en/tutorials/unittesting.html, which only got me so far. But, I was able to bootstrap Zend using a phpunit.xml file and pointing that to _bootstrap.php. Codeception is also able to bootstrap my tests using the _bootstrap.php file. So, now I can run my tests using both:
phpunit --bootstrap tests/unit/_bootstrap.php
and
php vendor/bin/codecept run unit
I was surprised to see how few examples there are for this. I was writing tests for a job queue client. Here is a bit of my test:
protected function setUp()
{
$this->serviceManager = new ServiceManager(new ServiceManagerConfig());
$config = Bootstrap::getConfig();
$this->serviceManager->setService('ApplicationConfig', $config);
$this->serviceManager->get('ModuleManager')->loadModules();
$this->client = $this->serviceManager->get('jobclient');
$this->client->addServers(array(array('ip' => '127.0.0.1', 'port' => '666')));
}
public function testServiceCreateSuccess() {
$this->client->setQueue($this->testData['queue']);
$this->assertEquals($this->client->getQueue(), $this->testData['queue'], 'We get the expected queue');
}
I mocked the job client and had a local config. My _bootstrap.php file looks basically the same as the Zend example except that I am using factories defined in the service config to manage some objects. So, I performed the "setService" method in the test setup rather then in the bootsrap init.

Laravel workbench unit test

What is the way to test my packages in workbench. If I write a unit test then no classes are autoloaded. So this means that:
<?php
use \Mockery as m;
class ExampleTest extends TestCase {
public function tearDown()
{
m::close();
}
/**
* A basic functional test example.
*
* #return void
*/
public function testShouldReturnValidServer()
{
$mock = m::mock('MailChimp[sendCurl]');
MailChimp::listSubscribe( array( 'id' => 'c79a023ff2', 'email_address' => 'dennieriechelman#gmail.com'));
}
}
results in a error saying that class TestCase is not found. When I add class TestCase to the autoload in my composer.json (the one in my package folder) the class is available. However then I get the next error that "Illuminate\Foundation\Testing\TestCase" is not available etc. etc.
So my question is what should I autoload in my composer.json in my package folder? Everything just like in my main composer.json or is there some other way that I am missing.
I know that in the manuel it says"
You may git init from the workbench/[vendor]/[package] directory and git push your package straight from the workbench! This will allow you to conveniently develop the package in an application context without being bogged down by constant composer update commands.
However I do not understand this. Can someone explain what is meant with this? By the way I am familiar with git. I just do not get the context.
EDIT1
As far I understand now is that you push your package to your repository and then include it in your main composer.json as package. I just do not see how this is helpful when developing. Hopefully I understand this wrong.. :)
EDIT2
I was wrong. You keep your package in workbench until it stable. Just like Nils pointed out below.The question still remains though. How do I create an environment in which I can unit test with the app started. I mean like testing a model where I can mock the facades etc. Or is doing this in the workbench bad practice?
I created a package for this purpose at https://github.com/orchestral/testbench
If you don't mind merging the results of your workbench testing with the results of your main application, you can simply add extra directories to your main phpunit.xml in your laravel root like this:
<testsuites>
<testsuite name="Application Test Suite">
<directory>./app/tests/phpunit/</directory>
<directory>./workbench/vendor/packageOne/tests/</directory>
<directory>./workbench/vendor/packageTwo/tests/</directory>
</testsuite>
</testsuites>
Then in the tests folder of your package, place your phpunit tests as normal, along with the TestCase.php file, adjusting the createApplication() function to be:
<?php
class TestCase extends \Illuminate\Foundation\Testing\TestCase {
public function createApplication()
{
$unitTesting = true;
$testEnvironment = 'testing';
return require './bootstrap/start.php';
}
Make sure your package composer.json auto-loads that TestCase.php file like so:
"autoload": {
"classmap": [
"tests/phpunit/TestCase.php"
]
}
Run composer dump-autoload -o to get everything aligned and then you should be able to run phpunit from your laravel root and it will test both your application and your packages.
Extend from the proper namespace and you should be able to run tests from package dir.
class ExampleTest extends \Illuminate\Foundation\Testing\TestCase {
..
}
See also Laravels neat testing helpers in workbench?

AngularJS mocking $logProvider in config block

Is there a way to inject providers when writing unit tests using Karma(Testacular) and Jasmine in angular?
Our team decided recently to use angularjs $log to write debugging details to the console. This way we can leverage the ability to disable the logging via the $logProvider.debugEnabled() method.
angular.module("App", ["prismLogin", "ui.bootstrap"])
.config(["$routeProvider", "$logProvider",
function ($routeProvider, $logProvider) {
$routeProvider
//routes here edited for brevity
//This is the offending line, it breaks several pre-existing tests
$logProvider.debugEnabled(true);
}]);
However after adding the $logProvider.debugEnabled(true); line several of our tests no longer execute successfully, failing with the following message:
TypeError: Object doesn't support property or method 'debugEnabled' from App
So my question again, is it possible to mock the $logProvider? Or should I provide my own configuration block for the test harness?
I attempted searching for a way to mock the app module with no luck. It seems to me that using the concrete app module instead of a mock is very brittle. I would like to avoid reworking tests associated with the app module every time a change is made in the app or run configuration blocks.
The tests that are failing are units of code with no relation to the $logProvider? I feel as if I a missing something here and making things much harder than they should be. How should one go about writing tests that are flexible and are not affected by other side effects introduced in your application?
It appears that this is a know issue with angular-mocks.
Until the issue is addressed , I was able to resolve the issue by adding the following method to the angular.mock.$LogProvider definition in angular-mocks.js at line 295.
this.debugEnabled = function(flag) {
return this;
};