You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ellar is compatible with `unittest` and `pytest` testing frameworks in python but in this documentation, we will be using `pytest`.
15
15
16
-
## Getting started
16
+
## **Getting started**
17
17
You will need to install `pytest`
18
18
19
19
```shell
20
20
pip install pytest
21
21
```
22
22
23
-
## Unit testing
23
+
## **Unit testing**
24
24
In the following example, we test two classes: `CarController` and `CarRepository`. For this we need to use `TestClientFactory` to build
25
25
them in isolation from the application since we are writing unit test.
26
26
@@ -29,8 +29,6 @@ We are going to be writing unit test for `CarController` in there.
29
29
30
30
```python
31
31
# project_name/car/tests/test_controllers.py
32
-
from unittest.mock import patch
33
-
34
32
from project_name.apps.car.controllers import CarController
35
33
from project_name.apps.car.schemas import CreateCarSerializer, CarListFilter
36
34
from project_name.apps.car.services import CarRepository
@@ -52,6 +50,45 @@ class TestCarController:
52
50
"name": "Mercedes",
53
51
"year": 2022,
54
52
}
53
+
```
54
+
In example above, we aren't really testing anything Ellar-specific. Notice that we are not using dependency injection; rather,
55
+
we pass an instance of `CarController` to our `CarRepository`.
56
+
This type of testing, where we manually instantiate the classes being tested, is commonly referred to as **isolated testing** because it is framework-independent
57
+
58
+
## **Using Test Factory**
59
+
**Test** factory function in `ellar.testing` package, is a great tool employ for a quick and better test setup.
60
+
Let's rewrite the previous example using the built-in `Test` class:
61
+
62
+
```python
63
+
# project_name/car/tests/test_controllers.py
64
+
from unittest.mock import patch
65
+
from ellar.di import ProviderConfig
66
+
from ellar.testing import Test
67
+
from project_name.apps.car.controllers import CarController
68
+
from project_name.apps.car.schemas import CreateCarSerializer, CarListFilter
69
+
from project_name.apps.car.services import CarRepository
'message': 'This action returns all cars at limit=10, offset=0'
70
107
}
71
108
```
72
-
In example above, we aren't really testing anything Ellar-specific. Notice that we are not using dependency injection; rather,
73
-
we pass an instance of `CarController` to our `CarRepository`. This type of testing, where we manually instantiate the classes being tested, is commonly referred to as **isolated testing** because it is framework-independent
74
-
## Using TestClientFactory
75
-
## Controller Testing
76
-
## Module Testing
77
-
## Mocking Services
109
+
With the `Test` class, you can create an application execution context that simulates the entire Ellar runtime,
110
+
providing hooks to easily manage class instances by allowing for mocking and overriding.
111
+
112
+
The `Test` class has a `create_test_module()` method that takes a module metadata object as its argument (the same object you pass to the `@Module()` decorator).
113
+
This method returns a `TestingModule` instance which in turn provides a few methods:
114
+
115
+
-[**`override_provider`**](#overriding-providers): Essential for overriding `providers` or `guards` with a mocked type.
116
+
-[**`create_application`**](#create-application): This method will return an application instance for the isolated testing module.
117
+
-[**`get_test_client`**](#testclient): creates and return a `TestClient` for the application which will allow you to make requests against your application, using the `httpx` library.
118
+
119
+
### **Overriding Providers**
120
+
`TestingModule``override_provider` method allows you to provide an alternative for a provider type or a guard type. For example:
121
+
122
+
```python
123
+
from ellar.testing import Test
124
+
125
+
classMockCarRepository(CarRepository):
126
+
pass
127
+
128
+
classTestCarController:
129
+
defsetup(self):
130
+
test_module = Test.create_test_module(
131
+
controllers=[CarController,]
132
+
).override_provider(
133
+
CarRepository, use_class=MockCarRepository
134
+
)
135
+
```
136
+
`override_provider` takes the same arguments as `ellar.di.ProviderConfig` and in fact, it builds to `ProvideConfig` behind the scenes.
137
+
In example above, we created a `MockCarRepository` for `CarRepository` and applied it as shown above.
138
+
We can also create an instance of `MockCarRepository` and have it behave as a singleton within the scope of `test_module` instance.
We can access the application instance after setting up the `TestingModule`. You simply need to call `create_application` method of the `TestingModule`.
### **Overriding Application Conf During Testing**
215
+
Having different application configurations for different environments is a best practice in software development.
216
+
It involves creating different sets of configuration variables, such as database connection details, API keys, and environment-specific settings,
217
+
for different environments such as development, staging, and production.
218
+
219
+
During testing, there two ways to apply or modify configuration.
220
+
221
+
=== "In a file"
222
+
In `config.py` file, we can define another configuration for testing eg, `class TestConfiguration` and then we can apply it to `config_module` when creating `TestingModule`.
223
+
224
+
For example:
225
+
226
+
```python
227
+
# project_name/config.py
228
+
229
+
...
230
+
231
+
class BaseConfig(ConfigDefaultTypesMixin):
232
+
DEBUG: bool = False
233
+
234
+
class TestingConfiguration(BaseConfig):
235
+
DEBUG = True
236
+
ANOTHER_CONFIG_VAR = 'Ellar'
237
+
238
+
```
239
+
We have created `TestingConfiguration` inside `project_name.config` python module. Lets apply this to TestingModule.
**End-to-end (e2e)** testing operates on a higher level of abstraction than unit testing, assessing the interaction between
274
+
classes and modules in a way that approximates user behavior with the production system.
275
+
276
+
As an application expands, manual e2e testing of every API endpoint becomes increasingly difficult,
277
+
which is where automated e2e testing becomes essential in validating that the system's overall behavior is correct and
278
+
aligned with project requirements.
279
+
280
+
To execute e2e tests, we adopt a similar configuration to that of unit testing,
281
+
and Ellar's use of **TestClient**, a tool provided by Starlette, to facilitates the simulation of HTTP requests
282
+
283
+
### **TestClient**
284
+
Starlette provides a [TestClient](https://www.starlette.io/testclient/) for making requests ASGI Applications, and it's based on [httpx](https://www.python-httpx.org/) library similar to requests.
0 commit comments