yanyongyu / githubkit

The modern, all-batteries-included GitHub SDK for Python, including rest api, graphql, webhooks, like octokit!
MIT License
158 stars 21 forks source link

Recommend a way how to test code consuming githubkit's models #98

Closed honzajavorek closed 2 months ago

honzajavorek commented 2 months ago

This is more of a question rather than issue, but I didn't see a Discussions tab, so posting it like this. I build an app which gets some data from GitHub and githubkit has proven very useful so far, thank you so much for building it!

What I struggle with is that I'd like to test my functions, but I don't know how to do it in a convenient way. Imagine a function like this:

async def has_linkedin(social_accounts: list[SocialAccount]) -> tuple[ResultType, str]:
    for account in social_accounts:
        if account.provider == "linkedin":
            return ResultType.DONE, f"Found LinkedIn: {account.url}"
    return ResultType.ERROR, "Add a link to your LinkedIn profile."

To test it, I need to somehow feed it with a list of SocialAccount objects which normally come from githubkit, populated by data from the API, but here I'd need to craft them manually. Which is expected for a test case, but these objects are typically very complex and full of various attributes.

Perhaps I could somehow record the API responses (how?) to fixtures (Python dict, JSON... doesn't really matter I guess) and populate the SocialAccount objects with it for the test case (how?), changing only the attributes which are important for the particular case.

But it feels like a lot of work. It's an atypical use case, which I believe isn't very well covered in the docs, so before I dive into reading code, I wanted to ask here for guidance, because maybe this is something you know how to solve with two lines of code which I'd be looking for several hours. I checked your tests folder, but I didn't find much inspiration on how to solve my problem.

yanyongyu commented 2 months ago

As you mentioned, the easiest way is to record the response data and save it (dict, JSON file, etc.). You can export the api response data by resp.text (raw str data) or resp.json() (json parsed dict/list).

After save the response data, you could rebuild the validated data with powerful Pydantic methods (Docs). For example:

from pydantic import TypeAdapter
from githubkit.versions.latest.models import SocialAccount

accounts: list[SocialAccount] = TypeAdapter(list[SocialAccount]).validate_json(json_content)
accounts: list[SocialAccount] = TypeAdapter(list[SocialAccount]).validate_python(python_list)
honzajavorek commented 2 months ago

This is awesome, thank you! Exactly what I was looking for. This one comment has saved me hours of work 😄