All Projects → cerbero90 → octane-testbench

cerbero90 / octane-testbench

Licence: MIT license
⛽ Set of utilities to test Laravel applications powered by Octane.

Programming Languages

PHP
23972 projects - #3 most used programming language

Projects that are alternatives of or similar to octane-testbench

pest-plugin-laravel-octane
⛽ Pest plugin to test Laravel applications powered by Octane.
Stars: ✭ 21 (-40%)
Mutual labels:  test, octane, laravel-octane
laravel-helm-demo
Example of a horizontally-scaled Laravel 8 app that runs on Kubernetes with NGINX Ingress Controller.
Stars: ✭ 33 (-5.71%)
Mutual labels:  octane, laravel-octane
react-native-diagnose
A framework to test a React Native app during runtime
Stars: ✭ 24 (-31.43%)
Mutual labels:  test
assert
Go 语言 assert 断言函数
Stars: ✭ 17 (-51.43%)
Mutual labels:  test
ccheck
A command line tool for validating Kubernetes configs with rego
Stars: ✭ 63 (+80%)
Mutual labels:  test
mockingbird
🐦 Decorator Powered TypeScript Library for Creating Mocks
Stars: ✭ 70 (+100%)
Mutual labels:  test
htest
htest is a http-test package
Stars: ✭ 24 (-31.43%)
Mutual labels:  test
beekeeper
Swarm Beekeeper is an orchestrator that can manage a cluster of Bee nodes and call into their API. It allows various scenario’s to be performed on these nodes. The Swarm team uses Beekeeper internally for integration tests.
Stars: ✭ 51 (+45.71%)
Mutual labels:  test
es-feature-detection
ECMAScript feature and API detection
Stars: ✭ 16 (-54.29%)
Mutual labels:  test
dextool
Suite of C/C++ tooling built on LLVM/Clang
Stars: ✭ 81 (+131.43%)
Mutual labels:  test
Jive.jl
some useful steps in tests 👣
Stars: ✭ 41 (+17.14%)
Mutual labels:  test
pynvme
builds your own tests.
Stars: ✭ 139 (+297.14%)
Mutual labels:  test
can-npm-publish
A command line tool that check to see if `npm publish` is possible.
Stars: ✭ 61 (+74.29%)
Mutual labels:  test
jpa-unit
JUnit extension to test javax.persistence entities
Stars: ✭ 28 (-20%)
Mutual labels:  test
cover.run
Code coverage
Stars: ✭ 34 (-2.86%)
Mutual labels:  test
J1939-Framework
Framework to work with J1939 Frames used in CAN bus in bus, car and trucks industries
Stars: ✭ 123 (+251.43%)
Mutual labels:  test
Android-Test
Android测试中常用到的脚本
Stars: ✭ 17 (-51.43%)
Mutual labels:  test
instant-mock
Quick and Easy web API mock server.
Stars: ✭ 27 (-22.86%)
Mutual labels:  test
eat
Json based scenario testing tool(which can have test for functional and non-functional)
Stars: ✭ 41 (+17.14%)
Mutual labels:  test
jest-retry
Jest retry pattern for flaky E2E tests
Stars: ✭ 36 (+2.86%)
Mutual labels:  test

Octane Testbench

Author PHP Version Laravel Version Octane Compatibility Build Status Coverage Status Quality Score Latest Version Software License PSR-12 Total Downloads

Set of utilities to test Laravel applications powered by Octane.

Install

Via Composer:

composer require --dev cerbero/octane-testbench

In tests/TestCase.php, use the TestsOctaneApplication trait:

use Cerbero\OctaneTestbench\TestsOctaneApplication;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use TestsOctaneApplication;
}

Now all tests extending this class, even previously created tests, can run on Octane.

Usage

In a nutshell, Octane Testbench

  1. is progressive: existing tests keep working, making Octane adoption easier for existing Laravel apps
  2. stubs out workers and clients: tests don't need a Swoole or RoadRunner server to run
  3. preserves the application state after a request, so assertions can be performed after the response
  4. offers fluent assertions tailored to Octane:
public function test_octane_application()
{
    $this
        ->assertOctaneCacheMissing('foo')
        ->assertOctaneTableMissing('example', 'row')
        ->assertOctaneTableCount('example', 0)
        ->expectsConcurrencyResults([1, 2, 3])
        ->get('octane/route')
        ->assertOk()
        ->assertOctaneCacheHas('foo', 'bar')
        ->assertOctaneTableHas('example', 'row.votes', 123)
        ->assertOctaneTableCount('example', 1);
}

Requests and responses

HTTP requests are performed with the same methods we would normally call to test any Laravel application, except they will work for both standard and Octane routes:

Route::get('web-route', fn () => 123);

Octane::route('POST', '/octane-route', fn () => new Response('foo'));


public function test_web_route()
{
    $this->get('web-route')->assertOk()->assertSee('123');
}

public function test_octane_route()
{
    $this->post('octane-route')->assertOk()->assertSee('foo');
}

Responses are wrapped in a ResponseTestCase instance that lets us call response assertions, any assertion of the Laravel testing suite and the following exception assertions:

$this
    ->get('failing-route')
    ->assertException(Exception::class) // assert exception instance
    ->assertException(new Exception('message')) // assert exception instance and message
    ->assertExceptionMessage('message'); // assert exception message

Furthermore, responses and exceptions can be debugged by calling the dd() and dump() methods:

$this
    ->get('failing-route')
    ->dump() // dump the whole response/exception
    ->dump('original') // dump only a specific property
    ->dd() // dump-and-die the whole response/exception
    ->dd('headers'); // dump-and-die only a specific property

Concurrency

Concurrency works fine during tests. However, PHP 8 forbids the serialization of reflections (hence mocks) and concurrent tasks are serialized before being dispatched. If tasks involve mocks, we can fake the concurrency:

// code to test:
Octane::concurrently([
    fn () => $mockedService->run(),
    fn () => 123,
]);

// test:
$this
    ->mocks(Service::class, ['run' => 'foo'])
    ->expectsConcurrency()
    ->get('route');

In the test above we are running tasks sequentially without serialization, allowing mocked methods to be executed (we will see more about mocks later).

If we need more control over how concurrent tasks run, we can pass a closure to expectsConcurrency(). For example, the test below runs only the first task:

$this
    ->expectsConcurrency(fn (array $tasks) => [ $tasks[0]() ])
    ->get('route');

To manipulate the results of concurrent tasks, we can use expectsConcurrencyResults():

$this
    ->expectsConcurrencyResults([$firstTaskResult, $secondTaskResult])
    ->get('route');

Finally we can make concurrent tasks fail to test our code when something wrong happens:

$this
    ->expectsConcurrencyException() // tasks fail due to a generic exception
    ->get('route');

$this
    ->expectsConcurrencyException(new Exception('message')) // tasks fail due to a specific exception
    ->get('route');

$this
    ->expectsConcurrencyTimeout() // tasks fail due to a timeout
    ->get('route');

Cache

Octane Testbench provides the following assertions to test the Octane cache:

$this
    ->assertOctaneCacheMissing($key) // assert the key is not set
    ->get('route')
    ->assertOctaneCacheHas($key) // assert the key is set
    ->assertOctaneCacheHas($key, $value); // assert the key has the given value

Tables

Octane tables can be tested with the following assertions:

$this
    ->assertOctaneTableMissing($table, $row) // assert the row is not present in the table
    ->assertOctaneTableCount($table, 0) // assert the number of rows in the table
    ->get('route')
    ->assertOctaneTableHas($table, $row) // assert the row is present in the table
    ->assertOctaneTableHas($table, 'row.column' $value) // assert the column in the row has the given value
    ->assertOctaneTableCount($table, 1);

Events

By default listeners for the Octane RequestReceived event are disabled to perform assertions on the application state. However we can register listeners for any Octane event if need be:

$this
    ->listensTo(RequestReceived::class, $listener1, $listener2) // register 2 listeners for RequestReceived
    ->get('route');

$this
    ->stopsListeningTo(TaskReceived::class, $listener1, $listener2) // unregister 2 listeners for TaskReceived
    ->get('route');

Container

Octane Testbench also introduces the following helpers to bind and mock services at the same time while preserving a fluent syntax:

$this
    ->mocks(Service::class, ['expectedMethod' => $expectedValue]) // mock with simple expectations
    ->mocks(Service::class, fn ($mock) => $mock->shouldReceive('method')->twice()) // mock with advanced expectations
    ->partiallyMocks(Service::class, ['expectedMethod' => $expectedValue]) // same as above but partial
    ->partiallyMocks(Service::class, fn ($mock) => $mock->shouldReceive('method')->twice())
    ->get('route');

Change log

Please see CHANGELOG for more information on what has changed recently.

Testing

composer test

Contributing

Please see CONTRIBUTING and CODE_OF_CONDUCT for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].