Skip to content

Commit 95b9ea1

Browse files
committed
Dev: Reviewed and expanded on PHP testing docs
1 parent 684a9de commit 95b9ea1

File tree

2 files changed

+91
-4
lines changed

2 files changed

+91
-4
lines changed

dev/docs/development.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ npm run production
2323
npm run dev
2424
```
2525

26-
BookStack has many integration tests that use Laravel's built-in testing capabilities which makes use of PHPUnit. There is a `mysql_testing` database defined within the app config which is what is used by PHPUnit. This database is set with the database name, username and password all defined as `bookstack-test`. You will have to create that database and that set of credentials before testing.
26+
Further details about the BookStack JavaScript codebase can be found in the [javascript-code.md document](javascript-code.md).
2727

28-
The testing database will also need migrating and seeding beforehand. This can be done by running `composer refresh-test-database`.
28+
## Automated App Testing
2929

30-
Once done you can run `composer test` in the application root directory to run all tests. Tests can be ran in parallel by running them via `composer t`. This will use Laravel's built-in parallel testing functionality, and attempt to create and seed a database instance for each testing thread. If required these parallel testing instances can be reset, before testing again, by running `composer t-reset`.
30+
BookStack has a large suite of PHP tests to cover application functionality. We try to ensure that all additions and changes to the platform are covered with testing.
3131

32-
If the codebase needs to be tested with deprecations, this can be done via uncommenting the relevant line within the TestCase@setUp function.
32+
For details about setting-up, running and writing tests please see the [php-testing.md document](php-testing.md).
3333

3434
## Code Standards
3535

dev/docs/php-testing.md

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# BookStack PHP Testing
2+
3+
BookStack has many test cases defined within the `tests/` directory of the app. These are built upon [PHPUnit](https://phpunit.de/) along with Laravel's own test framework additions, and a bunch of custom helper classes.
4+
5+
## Setup
6+
7+
The application tests are mostly functional, rather than unit tests, meaning they simulate user actions and system components and therefore these require use of the database. To avoid potential conflicts within your development environment, the tests use a separate database. This is defined via a specific `mysql_testing` database connection in our configuration, and expects to use the following database access details:
8+
9+
- Host: `127.0.0.1`
10+
- Username: `bookstack-test`
11+
- Password: `bookstack-test`
12+
- Database: `bookstack-test`
13+
14+
You will need to create a database, with access for these credentials, to allow the system to connect when running tests. Alternatively, if those don't suit, you can define a `TEST_DATABASE_URL` option in your `.env` file, or environment, with connection details like so:
15+
16+
```bash
17+
TEST_DATABASE_URL="mysql://username:password@host-name:port/database-name"
18+
```
19+
20+
The testing database will need migrating and seeding with test data beforehand. This can be done by running `composer refresh-test-database`.
21+
22+
## Running Tests
23+
24+
You can run all tests via composer with `composer test` in the application root directory.
25+
Alternatively, you can run PHPUnit directly with `php vendor/bin/phpunit`.
26+
27+
Some editors, like PHPStorm, have in-built support for running tests on a per file, directory or class basis.
28+
Otherwise, you can run PHPUnit with specified tests and/or filter to limit the tests ran:
29+
30+
```bash
31+
# Run all test in the "./tests/HomepageTest.php" file
32+
php vendor/bin/phpunit ./tests/HomepageTest.php
33+
34+
# Run all test in the "./tests/User" directory
35+
php vendor/bin/phpunit ./tests/User
36+
37+
# Filter to a particular test method name
38+
php vendor/bin/phpunit --filter test_default_homepage_visible
39+
40+
# Filter to a particular test class name
41+
php vendor/bin/phpunit --filter HomepageTest
42+
```
43+
44+
If the codebase needs to be tested with deprecations, this can be done via uncommenting the relevant line within the `TestCase@setUp` function. This is not expected for most PRs to the project, but instead used for maintenance tasks like dependency & PHP upgrades.
45+
46+
## Writing Tests
47+
48+
To understand how tests are written & used, it's advised you read through existing test cases similar to what you need to write. Tests are written in a rather scrappy manner, compared to the core app codebase, which is fine and expected since there's often hoops to jump through for various functionality. Scrappy tests are better than no tests.
49+
50+
Test classes have to be within the `tests/` folder, and be named ending in `Test`. These should always extend the `Tests\TestCase` class.
51+
Test methods should be written in snake_case, start with `test_`, and be public methods.
52+
53+
Here are some general rules & patterns we follow in the tests:
54+
55+
- All external remote system resources, like HTTP calls and LDAP connections, are mocked.
56+
- We prefer to hard-code expected text & URLs to better detect potential changes in the system rather than use dynamic references. This provides higher sensitivity to changes, and has never been much of a maintenance issue.
57+
- Only test with an admin user if needed, otherwise keep to less privileged users to ensure permission systems are active and exercised within tests.
58+
- If testing for the lack of something (e.g. `$this->assertDontSee('TextAfterChange')`) then this should be accompanied by some form of positive confirmation (e.g. `$this->assertSee('TextBeforeChange')`).
59+
60+
### Test Helpers
61+
62+
Our default `TestCase` is bloated with helpers to assist in testing scenarios. Some of these shown below, but you should jump through and explore these in your IDE/editor to explore their full capabilities and options:
63+
64+
```php
65+
// Run the test as a logged-in-user at a certain privilege level
66+
$this->asAdmin();
67+
$this->asEditor();
68+
$this->asViewer();
69+
70+
// Provides a bunch of entity (shelf/book/chapter/page) content and actions
71+
$this->entities;
72+
73+
// Provides various user & role abilities
74+
$this->users;
75+
76+
// Provides many helpful actions relate to system & content permissions
77+
$this->permissions;
78+
79+
// Provides a range of methods for dealing with files & uploads in tests
80+
$this->files;
81+
82+
// Parse HTML of a response to assert HTML-based conditions
83+
// Uses https://github.com/ssddanbrown/asserthtml library.
84+
$this->withHtml($resp);
85+
// Example:
86+
$this->withHtml($this->get('/'))->assertElementContains('p[id="top"]', 'Hello!');
87+
```

0 commit comments

Comments
 (0)