pytest-dev / pytest

The pytest framework makes it easy to write small tests, yet scales to support complex functional testing
https://pytest.org
MIT License
12.16k stars 2.69k forks source link

Make tmp_path truncation configurable or longer #10949

Open lodagro opened 1 year ago

lodagro commented 1 year ago

What's the problem this feature will solve?

Currently the tmppath is truncated to 30 chars. For longer test names this removes the `````` from the tmp_path. which is inconvenient

https://github.com/pytest-dev/pytest/blob/a15f54496293157b4c8f65164f86ba81c3d908a1/src/_pytest/tmpdir.py#L255

Describe the solution you'd like

Make this truncation length configurable or increase the max lenght (255 for example).

RonnyPfannschmidt commented 1 year ago

Please provide a example that demonstrates the issue more clearly

lodagro commented 1 year ago
import pytest

@pytest.mark.parametrize("a", range(1000, 1002))
@pytest.mark.parametrize("b", range(2000, 2002))
def test_with_a_very_long_name(tmp_path, a, b):
    print(tmp_path)

When running this the truncation is shown.

> pytest -sv

<snip>                                                                                                                             

test_issue10949.py::test_with_a_very_long_name[2000-1000] /tmp/pytest-of-wo904355/pytest-29/test_with_a_very_long_name_2000
PASSED
test_issue10949.py::test_with_a_very_long_name[2000-1001] /tmp/pytest-of-wo904355/pytest-29/test_with_a_very_long_name_2001
PASSED
test_issue10949.py::test_with_a_very_long_name[2001-1000] /tmp/pytest-of-wo904355/pytest-29/test_with_a_very_long_name_2002
PASSED
test_issue10949.py::test_with_a_very_long_name[2001-1001] /tmp/pytest-of-wo904355/pytest-29/test_with_a_very_long_name_2003
PASSED

After locally modifying the MAXVAL value in tmpdir.py to 255 gives the following. No truncation and fixture info is visible in the directory name.

> pytest -sv

<snip>     

test_issue10949.py::test_with_a_very_long_name[2000-1000] /tmp/pytest-of-wo904355/pytest-27/test_with_a_very_long_name_2000_1000_0
PASSED
test_issue10949.py::test_with_a_very_long_name[2000-1001] /tmp/pytest-of-wo904355/pytest-27/test_with_a_very_long_name_2000_1001_0
PASSED
test_issue10949.py::test_with_a_very_long_name[2001-1000] /tmp/pytest-of-wo904355/pytest-27/test_with_a_very_long_name_2001_1000_0
PASSED
test_issue10949.py::test_with_a_very_long_name[2001-1001] /tmp/pytest-of-wo904355/pytest-27/test_with_a_very_long_name_2001_1001_0
PASSED
RonnyPfannschmidt commented 1 year ago

thanks or showing this

we need to validate this with certain plarform limits typically hit on windows or osx (other posix is far nicer)

The-Compiler commented 1 year ago

255 bytes is generally a safe cross-platform limit.

Contrary to what @RonnyPfannschmidt says, Linux (ext) is actually the limiting factor here: For APFS (macOS since 2017) and NTFS, 255 characters is the limit - but on Linux, filesystem names are bytes. Assuming an UTF-8 locale, that might mean only 64 characters in the extreme case.

Getting this right in the general case is actually surprisingly hard, because that means you can't just cut off characters, and you also just can't cut off the encoded bytes (might end up with a partial character). Some while ago, I had some fun with trying to get this right for qutebrowser - it basically looks at how many bytes too big the encoded filename is, then cuts off excess // 4 characters, and repeats that until it fits.

Then again - as long as the (appropriately named) disable_test_id_escaping_and_forfeit_all_rights_to_community_support is left untouched, we escape node IDs to ASCII, and I suppose UTF-8 encoded filenames is a safe assumption on Linux, so we could in theory go for 255.

roj516 commented 5 months ago

Truncating to {prefix}_{hash}_{suffix}would help with readability and collisions.

The-Compiler commented 5 months ago

How would a hash make things more readable, or help with collisions any differently than a running counter which we already have?

roj516 commented 5 months ago

I have encountered (C++) libraries that are caching based on filename. Even though the directory is rm'd the repeated path leads to a collision.