<a id="onetick-py-test-features"></a>

# onetick-py-test plugin features

`pytest` introduces fixtures to simplify testing and share common resources between tests.

For more information about fixtures see
[api](https://docs.pytest.org/en/latest/reference.html#fixtures-api)
and [fixtures](https://docs.pytest.org/en/latest/fixture.html)
in the official pytest documentation.

Also see the [list](https://docs.pytest.org/en/latest/reference/fixtures.html#fixture) of fixtures
provided by pytest package itself.

Below are listed the fixtures provided by `onetick-py-test` package.

## Location fixtures

Fixtures that help to get directories.

| Name                 | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
|----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `cur_dir`            | gets the absolute path to the folder with the test.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `par_dir`            | gets the absolute path to the parent folder of the test.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `keep_generated_dir` | returns the absolute path to the folder were the test will be<br/>saved if the `keep-generated` flag is specified.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `otq_path`           | Allows to specify OTQ_PATH in [`onetick-py session config`](../../api/session/config.md#onetick.py.session.Config)<br/>with the location of OTQ files.<br/>By default OTQ_PATH is not specified for session fixtures.<br/><br/>You need to override this fixture to specify your own value.<br/><br/>```default<br/>import pytest<br/><br/>@pytest.fixture<br/>def otq_path(cur_dir):<br/>    return cur_dir / 'otqs'<br/><br/>def test_1(f_session):<br/>    # an instance of that `f_session` will search for otqs in<br/>    # specified path<br/>    ...<br/><br/>def test_2(f_session):<br/>    # the same with this instance of the `f_session`<br/>    ...<br/>```<br/><br/>#### NOTE<br/>The `otq_path` fixture will be automatically applied for all<br/>tests with the same scope. Scope visibility could be adjusted<br/>using modules and classes.<br/>For example<br/><br/>```default<br/>class TestCustomOTQS:<br/>    @pytest.fixture<br/>    def otq_path(self, cur_dir):<br/>        # this fixture will be used by any session fixtrue<br/>        # in this class<br/>        ...<br/><br/><br/>def test_1(f_session):<br/>    # ... but makes not effect on this session<br/>``` |

## Session fixtures

Session fixtures provide an instance of [`otp.Session`](../../api/session/session.md#onetick.py.Session)
to a test and take care of gracefully destroying it after.

| Name        | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `f_session` | The `function` scope session. A session instance is created<br/>before the test and destroyed after.<br/><br/>Example:<br/><br/>```default<br/>def test_1(f_session):<br/>    # `f_session` points to a new instance of the otp.Session<br/>    ...<br/><br/>def test_2(f_session):<br/>    # here `f_session` is a new instance<br/>    ...<br/>```                                                                                                                                                                                                                                                                                                          |
| `c_session` | The `class` scope session.<br/><br/>Example:<br/><br/>```default<br/>class TestSomething:<br/><br/>    def test_1(self, c_session):<br/>        # `c_session` is created for this class on the first occurance<br/>        ...<br/><br/>    def test_2(self, c_session):<br/>        # the `c_session` instance is the same as in test `test_1`<br/><br/><br/>class TestSomethingElse:<br/><br/>    def test_1(self, c_session):<br/>        # here the `c_session` is a new instance because it is a test<br/>        # of another test class<br/>        ...<br/>```<br/><br/>The `f_session` fixture in classes creates a new instance for every<br/>test. |
| `m_session` | The `module` scope session; it is created on the first<br/>usage and destroyed only when all tests in the test file are executed.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |

## Default values fixtures

| Name                 | Description                                                                                                                                                                            | Expected type   | Default             |
|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|---------------------|
| `default_tz`         | Allows to override the default<br/>timezone.                                                                                                                                           | str             | EST5EDT             |
| `default_start_time` | Start time for any query interval<br/>of the [`otp.run`](../../api/run.md#onetick.py.run)                                                                                              | str             | 2003/12/01 00:00:00 |
| `default_end_time`   | End time for any query interval<br/>of the [`otp.run`](../../api/run.md#onetick.py.run)                                                                                                | str             | 2003/12/04 00:00:00 |
| `default_symbol`     | Default symbol name that is used<br/>everywhere where OneTick requires it,<br/>for example any tick source like<br/>the<br/>[`otp.Source`](../../api/source/root.md#onetick.py.Source) | str             | AAPL                |
| `default_database`   | Default database that is used<br/>everywhere where OneTick expects it                                                                                                                  | str             | DEMO_L1             |

These fixtures are automatically picked up by the provided session fixtures such as `f_session`.
You just need to override a fixture with your value and it will be automatically picked up for all
fixtures with the same scope.

For example:

```default
@pytest.fixture
def default_tz():
   return 'GMT'

def test_something(f_session):
    # f_session picks up the `default_tz` value on initialization
    ...
```

#### NOTE
Default values come from the default OneTick installation that distributes a sample of trades
in the **DEMO_L1** database. Using this default values helps share issues
with the OneTick support team.

## The `--keep-generated` flag

<a id="keep-generated-flag"></a>

The plugin adds a custom `--keep-generated` flag to pytest that allows to control
the lifetime of generated resources during tests: config files for
[`otp.Session`](../../api/session/session.md#onetick.py.Session), databases, OTQ queries, etc.

It's helpful in case something goes wrong and a developer wants to take a closer look
into the resources generated during testing.

Description from the `pytest -h`:

```default
custom options:
  --keep-generated=KEEP_GENERATED

    Policy to keep temporary generated files, that has several options to run:
    * 'never' - do not keep any temporary generated files during the test run (default)
    * 'fail' - keep temporary generated files only when a test fails
    * 'always' - keep temporary generated files for every test
    Example: pytest --keep-generated=fail
```

This flag handles the folders and files that are created using the [`otp.TmpFile`](../../api/misc/tmp_file.md#onetick.py.utils.temp.TmpFile)
and [`otp.TmpDir`](../../api/misc/tmp_dir.md#onetick.py.utils.temp.TmpDir) correspondingly.

These classes are used in onetick-py internally to create databases,
log files and any configuration files related to the [`otp.Session`](../../api/session/session.md#onetick.py.Session).

Developers could also use these classes in code and tests to handle them in case of testing
and debugging.

Example:

```bash
$ pytest -vs --keep-generated=always
```

This command will print out the path to a folder with the saved resources:

```bash
$ pytest -vs

=========================== test session starts =====================
platform linux -- Python 3.9.6, pytest-7.1.2, pluggy-1.3.0 -- python3

OneTick build: 20230831120000, onetick-py: 1.82.0, onetick-py-test: 1.1.34
cachedir: .pytest_cache
rootdir: /project-folder
plugins: timeout-1.3.3, mock-1.11.0, pyfakefs-5.2.4, cov-2.7.1
collected 1 item

test_simple.py::test_simple
                 Time  BUY_SIZE  BUY_COUNT  SELL_SIZE  SELL_COUNT  FLAG
0 2023-12-01 00:00:01         5          1         27           2    -1
1 2023-12-01 00:00:02       100          1         70           1     1
2 2023-12-01 00:00:03        55          1         59           1     0
PASSED
[[ Generated resources: /tmp/test_user/run_20231129_101141_23129/test_my/test_simple ]]
```

This `[[ Generated resources: /tmp/test_user/run_20231129_101141_23129/test_my/test_simple ]]` line
points us where we could find the resources.

Let's go there and list the folder:

```bash
$ cd /tmp/test_user/run_20231129_101141_23129/test_my/test_simple
$ ls

boisterous-ant.locator  dancing-wombat.cfg  green-buffalo.run.otq
run.sh  tunneling-hippo.acl
```

* `dancing-wombat.cfg` is a OneTick config file that the test's session creates and uses
* `tunneling-hippo.acl` is the ACL that the `dancing-wombat.cfg` config points to
* `boisterous-ant.locator` is a locator file that the `dancing-wombat.cfg` config points to;
  it consists of databases that have been added into the test's session
* `green-buffalo.run.otq` is a query that has been passed into `otp.run` during tests;
  every call of that function dumps a query that can then be viewed as an OTQ
* the `run.sh` script allows to spin up a tick server using the saved configs and to play with the saved OTQ queries
  (On Windows it is the `run.bat` script)

## The `--show-stack-trace` flag

<a id="show-stack-trace-flag"></a>

Show stack trace with a line of `onetick.py` code where the issues has happened
in case of failure.

<!-- note :

It slows down a test run and could be sensitive if you have a lot of tests. -->

This flag enables the same mechanism like
the [`otp.config['show_stack_info']`](../../api/config.md#onetick.py.configuration.Config) flag does.

### Other

Our plugin adds OneTick version into the pytest output. You might find it in the
header of the output where `pytest` lists the plugins and their versions.

In the following example:

```bash
$ pytest -vs

=========================== test session starts =====================
platform linux -- Python 3.9.6, pytest-7.1.2, pluggy-1.3.0 -- python3

OneTick build: 20230831120000, onetick-py: 1.82.0, onetick-py-test: 1.1.34
cachedir: .pytest_cache
...
```

The following line shows OneTick related dependencies:

```bash
OneTick build: 20230831120000, onetick-py: 1.82.0, onetick-py-test: 1.1.34
```
