Question: I have the following pytest directory structure:

```
system_tests/
  ├── conftest
  ├── pytest.ini
  │
  ├── suite_1/
  │    └── test_A.py
  │   
  └── suite_2/
       └── sub_suite_2a/
            └── test_B.py

```

When each test method runs, a number of third-party libraries/processes generate artifacts in the current working directory.

* When pytest is executed from the `sub_suite` folder (using CLI or IDE "play" button), the files are generated in the `sub_suite` folder, where I want them to be.
* However, when pytest is run from the `system_tests` folder to run all tests, all artifacts are created in the `system_tests` folder, which is not what I want.

Is there an easy way to force pytest to always use the test class folder as the working directory so I get the same results regardless of *how* or *where* I run a test from?

Answer: 
**EDIT: Improved Solution**

Using [monkeypatch](https://docs.pytest.org/en/latest/how-to/monkeypatch.html) as suggested by @Kound removes the boilerplate code to restore the cwd. You can also enable [autouse](https://docs.pytest.org/en/latest/reference/fixtures.html#autouse-fixtures-are-executed-first-within-their-scope) to automatically apply this fixture to all test functions. Add the following fixture to [conftest.py](https://docs.pytest.org/en/latest/reference/fixtures.html#autouse-fixtures-are-executed-first-within-their-scope) to change the cwd for all tests:

```py
@pytest.fixture(autouse=True)
def change_test_dir(request, monkeypatch):
    monkeypatch.chdir(request.fspath.dirname)

```

Any processes that are kicked off by the test will use the test case folder as their working directory and copy their logs, outputs, etc. there, regardless of where the test suite was executed.

**Original Solution**

The following function-level fixture will change to the test case directory, run the test (yield), then change back to the calling directory to avoid side-effects, as suggested by @hi2meuk:

```py
@pytest.fixture
def change_test_dir(request):
    os.chdir(request.fspath.dirname)
    yield
    os.chdir(request.config.invocation_dir)

```

* `request` is a built-in pytest fixture
* `fspath` is the `LocalPath` to the test module being executed
* `dirname` is the directory of the test module
* `request.config.invocationdir` - the folder from which pytest was executed
* `request.config.rootdir` - pytest root, doesn't change based on where you run pytest. Not used here, but could be useful.
Many options open to you to achieve this. Here are a few.

1.
Write a pytest fixture to check if the current working directory is equal to the desired working directory, and if not, then move all the artifact files to the desired directory. **If the artifacts you are generating are all the same type of file (e.g. \*.jpg, \*.png, \*.gif) and you just want them to be in a different directory, then this may suffice.** Something like this could work

```
from pathlib import Path
import shutil

@pytest.fixture
def cleanup_artifacts():
    yield None
    cwd = Path.cwd()
    desired_dir = Path.home() / 'system-tests' / 'suite-2' / 'sub_suite_2a'
    if cwd != desired_dir:
        for f in cwd.glob('*.jpg'):
            shutil.move(f, desired_dir)

```

And then you can add this fixture to your tests as needed.

2.
You can configure the pytest `rootdir` to be the desired directory, since pytest uses the `rootdir` to store project/testrun specific info.

When you run pytest, run it as

```
pytest --rootdir=desired_path

```

See here for more info: <https://docs.pytest.org/en/latest/customize.html#initialization-determining-rootdir-and-inifile>

If both don't work for you, tell more about what your requirements are. Surely this can be done with pytest.