Generated extension¶
The generated extension looks like this, following the blog example from the previous chapter:
.
└── ebt_blog/
├── composer.json
├── ext_emconf.php
├── ext_localconf.php
├── ext_tables.php
├── ext_tables.sql
├── ExtensionBuilder.json
├── Classes/
├── Controller/..
└── Domain/
├── Model/..
└── Repository/..
├── Configuration/
├── ExtensionBuilder/..
├── TCA/..
└── TypoScript/..
├── Documentation/..
├── Resources/
├── Private/
├── Language/..
├── Layouts/..
├── Partials/..
└── Templates/..
└── Public/
└── Icons/..
└── Tests/
├── Functional/..
└── Unit/..
It is explained in more detail in the following sections:
Extension skeleton¶
This is the minimum set of extension files generated when only the required metadata has been entered into the properties form and no domain modeling has been performed:
.
└── ebt_blog/
├── composer.json
├── ext_emconf.php
├── ExtensionBuilder.json
├── Configuration/
└── ExtensionBuilder/..
├── Documentation/..
└── Resources/
└── Public/
└── Icons/
└── Extension.svg
The extension metadata is stored in the composer.json
and ext_emconf.php
files and is used for installations in Composer mode and Legacy mode
respectively.
The extension icon Extension.svg
is displayed in the list of extensions
of the Extension Manager module.
The Documentation/
folder contains a basic set of documentation files.
Read the section "Documentation" how to proceed with the documentation.
The Extension Builder stores some internal data in the ExtensionBuilder.json
file and in the Configuration/ExtensionBuilder/
folder which should be
kept as long as the extension is edited in the Extension Builder.
Domain modeling files¶
Most of the extension files are created for modeling the domain and configuring frontend plugins and backend modules:
.
└── ebt_blog/
├── ext_localconf.php
├── ext_tables.php
├── ext_tables.sql
├── Classes/
├── Controller/..
└── Domain/
├── Model/..
└── Repository/..
├── Configuration/
├── TCA/..
└── TypoScript/..
├── Resources/
├── Private/
├── Language/..
├── Layouts/..
├── Partials/..
└── Templates/..
└── Public/
└── Icons/..
└── Tests/
├── Functional/..
└── Unit/..
The frontend plugins are registered in the ext_localconf.php
file and
the backend modules are registered in the ext_tables.php
file.
The associated views are configured in the Configuration/TypoScript/
folder and the Fluid view templates are bundled in the Resources/Private/
folder.
The database schema of the domain model is defined in the ext_tables.sql
file.
The controller classes are provided in the folder Classes/Controller/
,
the classes that define the domain model are provided in the
folder Classes/Domain/
and their representation in the TYPO3 backend
is configured in the folder Configuration/TCA/
.
Last but not least, the tests of the classes are located in the folder
Tests/
.
For more information on tests, see the section "Tests" and for everything else, please refer to the Extbase & Fluid book of the official TYPO3 documentation.
Documentation¶
The Extension Builder has already created sample documentation for your extension if you have Generate documentation enabled in the properties form.
Writing documentation¶
The generated documentation is written in the reStructuredText (reST) markup language with support for Sphinx directives and provides a typical documentation structure with some dummy entries. More about how to document with reStructuredText and Sphinx can be found in the official TYPO3 documentation:
Render documentation¶
Once you have made changes to the documentation files, you should render them locally to test the output. The recommended method is to use the official TYPO3 Documentation Team Docker image, but you can also install all the required rendering tools from scratch. You can find more about this in the official TYPO3 documentation on the page "h2document:RenderingDocs/Index".
For example, on a Linux host with Docker installed, rendering boils down to these commands:
cd <path-to-extension>
source <(docker run --rm t3docs/render-documentation show-shell-commands)
dockrun_t3rd makehtml
xdg-open "Documentation-GENERATED-temp/Result/project/0.0.0/Index.html"
Publish documentation¶
If you publish the extension to the TYPO3 Extension Repository (TER), do not
put the rendered documentation under version control, as the documentation will
be registered during the publishing process for
automatic rendering and deployment to
https://docs.typo3.org/p/<vendor-name>/<extension-name>/<version>/<language>/
, for example to
https://docs.typo3.org/p/friendsoftypo3/extension-builder/11.0/en-us/
.
If the extension is for private use, you are free to do anything with the rendered documentation - including, of course, putting it under version control.
Tests¶
The TYPO3 Core is covered by thousands of tests of varying complexity: Unit tests (testing part of a class), functional tests (testing multiple classes in combination) and acceptance tests (testing the entire website user experience). To simplify testing, the general functionality for writing tests is bundled in the TYPO3 Testing Framework, and all custom tests should use it by inheriting from its base classes.
The Extension Builder generates a set of unit tests and a dummy functional test that easily cover the generated classes of your extension. The generated tests should encourage you to write your own tests once you start customizing the code.
If you are new to testing, we recommend that you invest some time to learn the benefits of software testing. It will certainly improve the quality of your software, but it will also boost your programming skills. Moreover, it will allow you to refactor without fear of breaking anything: Code that is covered by tests shows less unexpected behavior after refactoring.
Covered classes and methods¶
The Extension Builder generates unit tests for the public API of
- domain objects and
- default controller actions.
Covered domain object methods¶
The covered methods of domain object classes match the patterns
- get*()
- set*()
- add*()
- remove*().
For example:
/**
* @test
*/
public function setTitleForStringSetsTitle(): void
{
$this->subject->setTitle('Conceived at T3CON10');
self::assertEquals('Conceived at T3CON10', $this->subject->_get('title'));
}
All types of properties are covered, for example integers, strings, file references or relations to other domain objects.
Covered controller actions¶
The covered controller actions match the names
- listAction()
- showAction()
- newAction()
- createAction()
- editAction()
- updateAction()
- deleteAction()
and test the following behavior:
- asserting data in the action is assigned to the view and
- asserting the action delegates data modifications to a repository, like adding, updating, removing or fetching objects.
For example:
/**
* @test
*/
public function deleteActionRemovesTheGivenBlogFromBlogRepository(): void
{
$blog = new \Ebt\EbtBlog\Domain\Model\Blog();
$blogRepository = $this->getMockBuilder(\Ebt\EbtBlog\Domain\Repository\BlogRepository::class)
->onlyMethods(['remove'])
->disableOriginalConstructor()
->getMock();
$blogRepository->expects(self::once())->method('remove')->with($blog);
$this->subject->_set('blogRepository', $blogRepository);
$this->subject->deleteAction($blog);
}
Running tests¶
Unit tests of your extension can be executed in the TYPO3 backend using the phpunit extension or on the command line by following the testing pages of the official TYPO3 documentation.