Laravel workbench unit test - unit-testing

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?

Related

Symfony 4: how to load DataFixtures in a KernelTestCase

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.

Get Coverage stats when tests are in another package

My tests aren't in the same package as my code. I find this a less cluttered way of organising a codebase with a lot of test files, and I've read that it's a good idea in order to limit tests to interacting via the package's public api.
So it looks something like this:
api_client:
Client.go
ArtistService.go
...
api_client_tests
ArtistService.Events_test.go
ArtistService.Info_test.go
UtilityFunction.go
...
I can type go test bandsintown-api/api_client_tests -cover
and see 0.181s coverage: 100.0% of statements. But that's actually just coverage over my UtilityFunction.go (as I say when I ran go test bandsintown-api/api_client_tests -cover=cover.out and
go tool cover -html=cover.out).
Is there any way to get the coverage for the actual api_client package under test, without bringing it all into the same package?
As it is mentioned in comments you can run
go test -cover -coverpkg "api_client" "api_client_tests"
to run the tests with coverage.
But splitting code files from tests files to a different directories isn't a Go's way.
I suppose that you want to have a black-box testing(nothing package-private stuff can be accessible outside, even for tests).
To accomplish this it's allowed to have tests in another package(without moving the files). Example:
api_client.go
package api_client
// will not be accessible outside of the package
var privateVar = 10
func Method() {
}
api_client_test.go
package api_client_tests
import "testing"
func TestClient(t *testing.T) {
Method()
}

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.

trouble geting started with laravel testing and mockery

I'm trying to get started on unit testing with laravel and am trying to follow a couple of tutorials.
Alot of my controllers have been generated using Jeffrey Ways excellent generators and they appear to create their own tests so I thought it would be simple to get started.
I've installed mockery and sqlite - I've removed a lot of the tests from the folder for now so I can test one at a time but I'm having trouble with the first one that tests a create:
Here's my test:
<?php
use Mockery as m;
use Way\Tests\Factory;
class BooksTest extends TestCase {
public function __construct()
{
$this->mock = m::mock('Eloquent', 'Book');
$this->collection = m::mock('Illuminate\Database\Eloquent\Collection')->shouldDeferMissing();
}
public function setUp()
{
parent::setUp();
$this->attributes = Factory::book(['id' => 1]);
$this->app->instance('Book', $this->mock);
}
public function tearDown()
{
m::close();
}
public function testIndex()
{
$this->mock->shouldReceive('all')->once()->andReturn($this->collection);
$this->call('GET', 'books');
$this->assertViewHas('books');
}
public function testCreate()
{
$this->call('GET', 'books/create');
$this->assertResponseOk();
}
public function testStore()
{
$this->mock->shouldReceive('create')->once();
$this->validate(true);
$this->call('POST', 'books');
$this->assertRedirectedToRoute('books.index');
}
}
When I run phpunit I get lots of php messages around mockery - theres so much there I cant see the specifc error message
Is there a simple step I'm missing here in my set up??
I've added mockery to my composer.json and updated. I have not added anything to app.php in the config files - package didnt suggest I should or as a facade.
So I'm not sure, never having used it before whether mockery is installed correctly - although I assume it is. Was it necessary for me to add mockery to a laravel installation or is it part of a normal install?
Solved - definite PICNIC error
I needed to extend the buffer size of my command line to scroll back and see the error which identified the problem -
This is my first dip into testing so didnt quite expect the fail to go the way it did.
Tiny steps required

PHPUnit bootstrap in PhpStorm

I am working with Zend Framework 2 and I want to run tests for all of my modules in PhpStorm 5.0.4. I have PhpStorm set up to check for tests in myproject/module and it successfully finds my tests. The problem is that it doesn't read my configuration file within each module, which is needed (it points to a bootstrap file).
Here is the directory structure for a module (source):
/module
/User
/tests
/UserTest
/Model
/UserTest.php
Bootstrap.php
phpunit.xml.dist
TestConfig.php.dist
When I run the test, it gives me an error because Bootstrap.php is not run prior to running UserTest.php. All of the files are correct, because if I cd to /myproject/module/User/tests/ and run phpunit within the Terminal, it works fine.
I would like it to use the configuration (and thereby bootstrap) within each module. I tried to use the --configuration option with a relative path, but I couldn't get it to work.
Here is my current configuration:
Any pointers on how I can run the configuration file (and bootstrap) when a module is being tested? That is, a module has its own configuration file and bootstrap.
Thanks in advance.
PHP Storm 7 assumes that you will only need ONE default bootstrap file and thus does not enable individual bootsrap files DIRECTLY for each PHPUnit test configuration.
However, zf2 conducts tests on a per module basis. Thus, after you set the defaults to the first module the other modules don't work. The way around this is to
Remove the default options in File|Settings|PHP|PHPUnit
You don't have to remove the default configuration file but you must EMPTY OUT and uncheck the default bootstrap file. Just unchecking will not be enough
Go Run|Edit Configurations (there are other shortcuts to this box)
For each module you have to create a test configuration. For example, you'll have the standard Application Module and thus an "Application Module Test" for it, maybe an Admin Module and then an "Admin Module Test" for that
For each test (assuming standard zf2 directory structure)
a. Test Scope: Directory
b. Directory: C:\wamp\www\PROJECT-NAME\module\MODULE-NAME\test
c. Check "Use alternative configuration file:"
d. Enter C:\wamp\www\PROJECT-NAME\module\MODULE-NAME\test\MODULE-NAMETest\phpunit.xml.dist
e. In "Test Runner options", enter "--bootstrap C:\wamp\www\PROJECT-NAME\module\MODULE-NAME\test\MODULE-NAMETest\Bootstrap.php"
Repeat for next module
The issue here is that as long as the default bootsrap field has an entry, phpstorm will add that as default as a --bootstrap option AFTER whatever you put in the case specific Test Runner options. So, no matter what you do, you end up running the wrong bootstrap file everytime except for the first/default test case
Hope this helps
Unless I missed something, you'll have to set up a test configuration for each module. In your case, you have myproject. Instead, you'll want one for each module, and then set up the configuration for each (Use alternative configuration file).
I make use of the environment variables option in the run configuration to to define a value I can use within a global bootstrap.php to pull in requirements specific to a given module or section of the application.
class GlobalBootstrap
{
private static $applicationSections = [
'section_a',
'section_b',
'section_c'
];
public static function init()
{
$localMethod = self::fetchLocalMethod();
if (!is_null($localMethod)) {
self::$localMethod();
} else {
throw new Exception(
__CLASS__
. '::'
. __FUNCTION__
. 'Says: No local method has been defined for this test section'
);
}
}
private static function fetchLocalMethod()
{
$section = getenv('APPLICATION_SECTION');
if (is_null($section) || !in_array($section, self::$applicationSections)) {
return null;
}
$section = preg_replace("/[^a-zA-Z]+/", "", $section);
$method = 'bootstrap' . ucfirst(strtolower($section));
return $method;
}
/**
* Section specific methods
*/
protected static function bootstrapSectiona()
{
require __DIR__ . '/../../{section_a}/module/Test/Bootstrap.php';
}
}
GlobalBootstrap::init();
Any arbitrary variable and value can be created and then referenced in your bootstrap.php using: getevn(VARIABLE_NAME); This saves a lot of long-winded configuration in PHPStorm, but culd potentially get equally as complex if you're relying on a lot of differing bootstrap functionality.