Load fixtures to Testdb with PHPUnit and extbase - phpunit

I search for a way to load test-data to a MySQL in my phpunit testcase. I use typo3 4.5 and want to test my pages-override and some functions in my testcase. I don't want to create all models ever and ever by hand, and would like to load a test-db and some sql-file for each test. Is this possible?

In the tests for our TYPO3 extensions, we run $GLOBALS['TYPO3_DB']->exec_INSERTquery() calls with test data in setUp(). tearDown() makes exec_DELETEquery() calls.
Test data get names like "unittest-FOO", so that we can delete all "unittest-%" entries when cleaning up.
Alternatively, you can use the phpunit extension for TYPO3 - it adds a column to each table that indicates if a record is a test datum or not. Cleaning up afterwards is easy then.

I resolved this problem by loading a complete testdatabase in my setup method. It works for me. For some inserts i will try to use
function setUp() { $this->db->exec("BEGIN"); }
function tearDown() { $this->db->exec("ROLLBACK"); }
like here

Related

Laravel 5.7 testing with RefreshDatabase trait throws ErrorException: Trying to access array offset on value of type int

so as I stated in the title, I am working on Laravel 5.7 project and am making first tests in this application (big system). We did not make any tests in here yet, so this problem is the first time here.
For every test, this is how the controller uses the trait
use RefreshDatabase;
protected function setUp()
{
parent::setUp();
$this->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class);
$this->withoutExceptionHandling();
}
As you can see, I am just trying to use the trait to refresh the DB after the tests are done.
The problem arises when I call to execute the tests.
ErrorException: Trying to access array offset on value of type int
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Input\ArrayInput.php:135
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Input\Input.php:55
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Command\Command.php:214
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Console\Command.php:170
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Application.php:886
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Application.php:262
C:\laragon\www\demi\systems\damaro\vendor\symfony\console\Application.php:145
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Console\Application.php:89
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Console\Application.php:188
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php:250
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\PendingCommand.php:136
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\PendingCommand.php:218
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithConsole.php:55
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\RefreshDatabase.php:55
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\RefreshDatabase.php:18
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestCase.php:104
C:\laragon\www\demi\systems\damaro\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestCase.php:71
This is the whole trace.
Some solutions I found are:
composer update - not an option, because the project is in production
disable telescope package in phpunit.xml - did not work
I also tried installing telescope package - did not work as well
Do you have any idea?
So I have not found an answer to this question, but I have found a workaround.
Instead of using RefreshDatabase trait I decided to use DatabaseTransactions trait.

Is there any way to get the c# object/data on which NUnit test is failing?

I am writing unit tests for a complex application which has so many rules to be checked into a single flow by using NUnit and Playwright in .Net5. Actually the case is, to save the time for writing the test scripts for Playwright (front-end testing tool), we have used a library named Bogus to create dummy data dynamically based on the rules (because the test cases has numerous rules to be checked and it was much more difficult to write fresh data to every case). I am using Playwright script into the NUnit test and providing the data source by using [TestCaseSource("MethodName")] to provide dynamic data object for different cases.
Now, we are facing a problem that some of the tests cases get passed and some are failed and we are unable to identify that particularly which test case is causing the problem because the testcase data is being provided by the dynamic source and in that source the data is being generated by the Bogus library on the bases of the rules which we have generated. Plus, we cannot look at the tests for a long time that's why we have automated the process.
[Test]
[TestCaseSource("GetDataToSubmit")]
public async Task Test_SubmitAssignmentDynamicFlow(Assignment assignment)
{
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
{
Headless = false,
...
});
....
private static IEnumerable<TestCaseData> GetDataToSubmit()
{
//creating data for simple job
var simpleAssignment = new DummyAssigmentGenerator()
....
.Generate();
yield return new TestCaseData(simpleAssignment);
....
Now, my question is, is there any way so that we can view that what were the actual values in the object in the failed case, when we see the whole report of the testcases? So that we can come to know that which certain values are causing problems and eventually fixed those.
Two approaches...
Assuming that DummyAssignmentGenerator is your own class, override its ToString() method to display whatever you would like to see. That string will become part of the name of the test case generated, like...
Test_SubmitAssignmentDynamicFlow(YOUR_STRING)
Apply a name to each TestCaseData item you yield using the SetName() fluent method. In that case, you are supplying the full display name of the test case, not just the part in parentheses. Use {m}(YOUR_STRING) in order to have it appear the same as in the first approach.
If you can use it, the first approach is clearly the simpler of the two.

How to manipulate the application configs for controller tests?

I'm writing functional / controller tests for a ZF3 application (driven by PHPUnit and zendframework/zend-test). Like this:
public function testWhatEver()
{
$this->dispatch('/');
$this->assertResponseStatusCode(Response::STATUS_CODE_200);
}
It's working pretty well. But now I got a case, where I need to test the application with multiple mutually exclusive configs.
E.g., the case "authentication": The application provides multiple authentication methods (let's say: AuthA, AuthB,AuthC). (That is configurable via setting of the auth.type's value in the config file.) I want to test each of them. That means, it's not enough to have special test configs in the /config/autoload/test/*{local|global}.php. I need to be able to manipulate them for every test (before I call the dispatch(...) method).
How to manipulate the application configs for / from controller tests (on the fly)?
If no better solution can be found, a possible workaround might be to edit the config file (by using file_put_contents(...) or something like this) before every test. But it's a bit ugly (and slow).
In general I see no really nice solution for this problem. But there some more or less acceptable workaround:
Workaround 1: manipulating the according config file for every test
$configs = file_get_contents(...)
searchByRegexAndManipulateConfigs(...)
file_put_contents(...)
It's much effort and would make the testing slower (due to reading from / writing to the filesystem).
Workaround 2: simple files with only one config value
We can create files like config.auth.type.php or config.auth.type.txt (one per config value t keep the file really simple) and to use inclue or file_get_contents(...) call as value in the config. The the value in the file needs to be manipulated before the test execution.
It's a bit less effort (we don't need to write complex RegEx), but might make the test considerably slower, since every application request would start by reading an additional file.
Workaround 3: passing configs values through GLOBALS
It's the simplest and fastest variant. We just save the needed value into a global variable and read it in the config (file's) array. After the test we remove the variable:
AuthBTest
...
protected function setUp() // or setUpBeforeClass()
{
parent::setUp();
$GLOBALS['appTestConfigs']['auth.type'] = 'AuthA';
}
protected function tearDown() // or tearDownAfterClass()
{
parent::tearDown();
unset($GLOBALS['appTestConfigs']);
}
...
/config/autoload/test/local.php
return [
'auth' => [
'type' => isset($GLOBALS['appTestConfigs']['auth.type']) ? $GLOBALS['appTestConfigs']['auth.type'] : 'AuthA',
],
];

how to skip execution of phpunit data provider method

One of my phpunit tests uses a dataset (that is provided by a dataprovider) that takes quite a long time to generate. When I exclude this test from execution, its dataprovider method is still executed.
How can I skip execution of a dataprovider?
If you're skipping the slow tests from inside the test, using $this->markTestSkipped(), you can't prevent the dataProvider to be executed.
This is because PHPUnit must get the data that will be passed to the tests, before executing them.
Possible solutions:
Set an environment variable from command-line (-d key[=value] option) that will be read both by the dataProvider and the slow test. The dataProvider will return a dummy array and the test will mark itself as skipped.
Mark the test as slow using the #group annotation and use the --exclude-group command line option so the slow group tests won't be executed
Refactoring the test so no dataProviders are used, assuming the inconvenience of not having the tests as distinct cases.

how to unit testing cache layer

I have added a cache layer to my project . now I wonder if I could unit test methods that manipulate cache ? or is there a better way to test Layer's logic ?
I just want to check the process , for example :
1- when the item is not in the cache , method should hit the database
2- the next time method should use cache
3- when a change is made to database , cache should be cleared
4- if data retrieved from databse is null , it shouldn't be added to cache
I want to ensure that the logic I have placed into the methods are working as expected .
I'm presuming the cache is a third party cache? If so, I would not test it. You're testing someone else's code otherwise.
If this caching is so important you need to test it, I'd go with an integration or acceptance test. In other words, hit the page(s)/service(s) in question and check the content that way. By the very definition of what you wish to test, this is not a unit test.
On the flip side, if the cache is one you've rolled yourself, you'll easily be able to unit test the functionality. You might want to check out verification based testing in order to test the behavior of the cache, as apposed to actually checking stuff is added/removed from the cache. Check out mocking for ways to achieve this.
To test for behaviour via Mock objects (or something similar) I'd do the following - although your code will vary.
class Cacher
{
public void Add(Thing thing)
{
// Complex logic here...
}
public Thing Get(int id)
{
// More complex logic here...
}
}
void DoStuff()
{
var cacher = new Cacher();
var thing = cacher.Get(50);
thing.Blah();
}
To test the above method I'd have a test which used a mock Cacher. You'd need to pass this into the method at runtime or inject the dependency into the constructor. From here the test would simply check that cache.Get(50) is invoked. Not that the item is actually retrieved from the cache. This is testing the behavior of how the cacher should be used, not that it is actually caching/retrieving anything.
You could then fall back to state based testing for the Cacher in isolation. E.g you add/remove items.
Like I said previously, this may be overkill depending on what you wish to do. However you seem pretty confident that the caching is important enough to warrant this sort of testing. In my code I try to limit mock objects as much as possible, though this sounds like a valid use case.

Resources