Giter VIP home page Giter VIP logo

Comments (4)

tamird avatar tamird commented on June 9, 2024

There's another issue with not being able to specify a suffix:

  • If my comparisons are as written above (v2 then v1) then when I add a new version it'll go ahead of v2, which means all my fixtures will change.
  • if my comparisons are in ascending version order then when I remove an old version then all my fixtures will change.

from pytest-insta.

vberlier avatar vberlier commented on June 9, 2024

There's no concept of a "suffix". Either you specify the full name, and the extension is extracted to select the correct snapshot format, or you just specify the extension, and the name is generated for you.

So here snapshot("v2.json") uniquely identifies a specific snapshot for the current test. You can only match it multiple times if all the assertions are supposed to produce the same output. So for example matching the same snapshot in a loop with different inputs won't work.

The closest thing to a suffix would be making pytest-insta recognize a custom extension for your different API versions by defining a custom snapshot format in your conftest.py:

# conftest.py
from pytest_insta import FmtJson

class FmtApiV1(FmtJson):
    extension = ".v1.json"
    
class FmtApiV2(FmtJson):
    extension = ".v2.json"

Then the code you showed earlier will generate a unique name with the custom extension.

Otherwise I'd suggest writing separate tests for v1 and v2, or using a parametrized test with a single snapshot("json") assertion that will run for each API version:

# test_api.py
@pytest.mark.parametrize("api_version", ["v2", "v1"])
async def test_foo(api_version, client):
    if api_version == "v2":
        result = await client.get_new_api()
    else:
        result = await client.get_old_api()
    assert snapshot("json") == result.json()

The generated snapshot name will automatically take into account the parameterized test (e.g.: api__foo__v2__0.json).

The snapshot counter resets for each parameter so the index won't "slide" and invalidate existing snapshots if you add or remove api versions this way.

Depending on your use case you could even bundle this into a fixture and have a hybrid client for tests:

# conftest.py
@pytest.fixture(scope="module", params=["v2", "v1"])
def hybrid_client(request):
    if request.param == "v2":
        return ClientV2()
    else:
        return ClientV1()
# test_api.py
async def test_foo(hybrid_client):
    assert snapshot("json") == (await hybrid_client.get_common_api()).json()
    if isinstance(hybrid_client, ClientV2):
        assert snapshot("json") == (await hybrid_client.get_new_api()).json()
    if isinstance(hybrid_client, ClientV1):
        assert snapshot("json") == (await hybrid_client.get_old_api()).json()

Hope this helps :)

from pytest-insta.

tamird avatar tamird commented on June 9, 2024

There's no concept of a "suffix". Either you specify the full name, and the extension is extracted to select the correct snapshot format, or you just specify the extension, and the name is generated for you.

So here snapshot("v2.json") uniquely identifies a specific snapshot for the current test. You can only match it multiple times if all the assertions are supposed to produce the same output. So for example matching the same snapshot in a loop with different inputs won't work.

Yep, this is what I wrote in the issue description.

The closest thing to a suffix would be making pytest-insta recognize a custom extension for your different API versions by defining a custom snapshot format in your conftest.py:

# conftest.py
from pytest_insta import FmtJson

class FmtApiV1(FmtJson):
    extension = ".v1.json"
    
class FmtApiV2(FmtJson):
    extension = ".v2.json"

Then the code you showed earlier will generate a unique name with the custom extension.

This would work, but it requires a separate class for every version, which is quite tedious.

Otherwise I'd suggest writing separate tests for v1 and v2, or using a parametrized test with a single snapshot("json") assertion that will run for each API version:

# test_api.py
@pytest.mark.parametrize("api_version", ["v2", "v1"])
async def test_foo(api_version, client):
    if api_version == "v2":
        result = await client.get_new_api()
    else:
        result = await client.get_old_api()
    assert snapshot("json") == result.json()

The generated snapshot name will automatically take into account the parameterized test (e.g.: api__foo__v2__0.json).

This works of course, but imagine that I have a test with with very expensive setup - I don't want to repeat that setup for each test case. I could do something complicated with fixture scopes, but it doesn't work in the most general case (e.g. where something about the test case wants to change the setup, but I still want to test all API versions).

The snapshot counter resets for each parameter so the index won't "slide" and invalidate existing snapshots if you add or remove api versions this way.

Depending on your use case you could even bundle this into a fixture and have a hybrid client for tests:

# conftest.py
@pytest.fixture(scope="module", params=["v2", "v1"])
def hybrid_client(request):
    if request.param == "v2":
        return ClientV2()
    else:
        return ClientV1()
# test_api.py
async def test_foo(hybrid_client):
    assert snapshot("json") == (await hybrid_client.get_common_api()).json()
    if isinstance(hybrid_client, ClientV2):
        assert snapshot("json") == (await hybrid_client.get_new_api()).json()
    if isinstance(hybrid_client, ClientV1):
        assert snapshot("json") == (await hybrid_client.get_old_api()).json()

Hope this helps :)

Again, this doesn't solve for the scenario I describe above :(

from pytest-insta.

vberlier avatar vberlier commented on June 9, 2024

Then I'd simply recommend making your own wrapper for implementing a naming scheme that suits your specific use-case:

# conftest.py
@pytest.fixture
def api_snapshot(snapshot: SnapshotFixture):
    d: dict[str, int] = {}

    def wrapper(version: str):
        i = d.setdefault(version, 0)
        d[version] = i + 1
        return snapshot(f"{i}_{version}.json")

    return wrapper
assert api_snapshot("v2") == (await client.get_new_api()).json()
assert api_snapshot("v1") == (await client.get_old_api()).json()

This way you can have independent counters for all API versions without relying on a parametrized test. This will prevent snapshot indices from clashing when you add or remove versions, and you're free to expand it further to meet any additional requirement you might have.

from pytest-insta.

Related Issues (7)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.