#unit-testing

1 messages ยท Page 7 of 1

drifting sorrel
#

Why not? ๐Ÿค”

viscid basalt
drifting sorrel
#

Agree that using a pattern like that is a good practice in general, wouldn't you need to monkeypatch the repository then?

ember maple
drifting sorrel
# viscid basalt How? ๐Ÿ˜…

I think you might have misunderstood what I meant. If you would put the entire db query in a plain Python function, that takes data as input, and returns data as output you can quite easily monkey patch it.

viscid basalt
#

I don't think that's possible in python, and if it is - I think it's not very practical?

drifting sorrel
viscid basalt
#

I mean, how do you monkeypatch a function?

ember maple
viscid basalt
#

def a():
    return "a"

def b():
    print(a())

How would I monkeypatch a here?

drifting sorrel
viscid basalt
drifting sorrel
#

A lot simpler than implementing a proper repository pattern, even if that is a good practice!

viscid basalt
#

Also if it's imported you'd have to monkeypatch module it is imported in

drifting sorrel
viscid basalt
#

Repository pattern is simpler since you could just provide a mock implementation instead

#

Or patch a specific method

ember maple
viscid basalt
ember maple
#

And welcome to one of the reasons why its called "monkey" patching

drifting sorrel
#

You would need a repository stub, i.e. more test code. But I don't disagree that it is a good pattern. Monkey patching has it's use cases too, for sure. Very simple and easy to grasp

viscid basalt
#

The person just needed to use a dependency override in fastapi ๐Ÿค”
In case of sqlalchemy you can reconfigure a session maker instance for tests too

ember maple
drifting sorrel
#

Try that, and then compare it with patching one single function afterwards ๐Ÿ˜„

viscid basalt
#

e.g.

session_factory = async_session_maker()

async def get_db() -> Iterator[AsyncSession]:
    async with session_factory() as session:
        yield session
session_factory.configure(bind=...)
#

Or override dependency in fastapi:

app.dependency_overrides[get_db] = new
yield
del app.dependency_overrides[get_db]
ember maple
#

It's quite unfortunate the python dependency injection story is so fragmented

drifting sorrel
viscid basalt
#

It overrides a fastapi dependency

#

I.e. only if you use it like this: Depends(get_db)

drifting sorrel
viscid basalt
#

What would be the difference?

drifting sorrel
#

Overwriting is basically monkey patching, as I see it. Overriding is extending an existing behaviour (such as inheritance) and over-riding a default behaviour.

viscid basalt
#

You can do anything you want, really ๐Ÿค” e.g. you could use old dependency in your new dependency

#

I don't understand the distinction though

viscid basalt
#

Different frameworks try to incroporate DI too but it's usually misused

pearl cliff
#

what's the value in a DI framework? i never really understood that

viscid basalt
pearl cliff
#

ahh, i see

ember maple
pearl cliff
#

in that case, would pytest fixtures be considered a DI framework?

viscid basalt
#

e.g. in case of a typical web app you may need:

session -> RepositoryA,RepositoryB -> Service -> UseCase

Resolving that by hand would get verbose

viscid basalt
ember maple
#

Pytest fixtures are a di framework, unfortunately very organic instead of organized

pearl cliff
#

i've used Depends in fastapi which i know is very much injecting a dependency, but i see it as more of a convenience than something i can fundamentally structure my design around

ember maple
#

Python makes numerous things very easy,so oftentimes by the time you realize you could use an di framework, starting to use one will be unfathomably expensive

viscid basalt
viscid basalt
# pearl cliff i've used `Depends` in fastapi which i know is very much injecting a dependency,...

There's a couple issues with depends:

  1. Dependencies are closed after the response is sent as of right now
  2. You obviously can't use it outside of fastapi
  3. You have to import fastapi into your domain logic, which isn't that good, but it's not that bad either, if you don't want to import it you'd have to wrap all of your classes into functions that would resolve them in fastapi layer
  4. Basic support something like singletons would be nice too
#

If you need to support API and something else fastapi's di goes out of the window

proud nebula
viscid basalt
proud nebula
pearl cliff
viscid basalt
pearl cliff
#

you'd have to write your own logic to interpret these Depends annotations if you wanted to use them outside of fastapi

viscid basalt
#

e.g. I have a CLI and want to use depends here

proud nebula
#

Surely there's a function in fastapi that does the injecting, you can just call that.

pearl cliff
#

have you seen the fastapi source code?

viscid basalt
proud nebula
pearl cliff
#

i mean, that's kind of a bold statement to make about any framework

ember maple
#

I wish someone would wrap svcs by hynek

pearl cliff
#

what would such a function even look like?

#

ultimately all Depends does is call a generator function

#

(or an async generator function)

#

the framework magic is all doing that within the asgi lifecycle

#

Dependencies are closed after the response is sent as of right now
@viscid basalt so a more full-featured DI framework might allow me to define various scopes? like a dependency that's scoped to a client's login session?

viscid basalt
#

@pearl cliff For me the best solution is to use fastapi's DI where it makes sense (e.g. getting something from a request, like a header) and using separate DI for everything else:

async def get_user(header: str = ...) -> User:
    pass

@get
@inject
async def endpoint(
    user: Annotated[User, Depends(get_user)],
    service: Annotated[Service, Inject]
) -> ...:
    ...
viscid basalt
#

"Classic" di implementation defines 3 lifecycles - singleton, scoped and transient

pearl cliff
#

(i'm happy to read about this in a book or whatever if you don't want to explain it all now)

viscid basalt
#

scoped scoped to a di "request" and cached, transient dependency would provide new instance to each object requesting it

pearl cliff
#

i mean, that does sound a lot like what fastapi does

viscid basalt
#

Fastapi only has scoped dependencies

pearl cliff
#

Depends aren't cached though, right?

viscid basalt
#

It is

pearl cliff
#

wat

viscid basalt
#

(In a context of request)

pearl cliff
#

oh

#

ahhh i see

#

but surely a transient dependency becomes "scoped" as soon as i pass it somewhere as a function parameter, right?

#

or is the idea that you don't do that

#

wouldn't i just want DI at the edges of some sub-unit within my code, and then pass around capability objects or w/e therein?

viscid basalt
#

Let's imagine we have a di framework:

container = Container()
container.add_singleton(Singleton)
container.add_scoped(Scoped)
container.add_transient(lambda: random.random(), float)

Singleton will behave this way:

with container.request() as req:
    s1 = req.get(Singleton)

with container.request() as req:
    s2 = req.get(Singleton)

s1 is s2 # True

Scoped


with container.request() as req:
    s1 = req.get(Scoped)
    s1 is req.get(Scoped)

with container.request() as req:
    s1 is not req.get(Scoped)
#
with container.request() as req:
    req.get(float) != req.get(float)
#

That's how lifecycles usually work

#

In case a transient dependency if for example you have 2 scoped dependencies and they each request a transient one - they'll get different instances

pearl cliff
#

yeah, that makes sense

#

am i weird if i kind of don't like that

viscid basalt
#

Maybe ๐Ÿ™‚

pearl cliff
#

unless i'm mistaken, fastapi depends can only be "requested" once, from the top-level route handler fucntion

viscid basalt
proud nebula
#

It's certainly a lot easier to understand if there is only one scope

pearl cliff
#

sure. but once you're inside the handler function, whatever dependency you obtained you can pass around as a regular object, as a function parameter, instance attribute, whatever

proud nebula
#

(kinda like how there's only one scope in python functions, unlike most programming languages)

viscid basalt
#

You can't do something like

def myfunc(b = Depends(B), a: A):
    pass

@get
async def endpoint(a: A = Depends(A)):
    b(a=a)
pearl cliff
#

right. are you saying that a more general DI framework would allow that?

viscid basalt
pearl cliff
#

ah okay, you dislike the thing i was about to say i am having an instinctively negative reaction to ๐Ÿ˜†

viscid basalt
#

I would use a service locator pattern if you need to provide something after the initial injection

#

Usually if it's something dynamic

pearl cliff
#

right, in my mind things like fastapi Depends convert dynamic scope to lexical scope

viscid basalt
#

e.g.

storages = {...}
storage_cls = storages[name}
storage = context.get(storage_cls)
pearl cliff
#

didn't know there was a name for that. good to remember

viscid basalt
#

Writing your own DI is pretty simple btw ๐Ÿ˜‰

ember maple
viscid basalt
pearl cliff
#

seems like it's easy to write a rudimentary one

#

i imagine that doing it well is a big design challenge

viscid basalt
#

It obviously depends on what kind of features you need

pearl cliff
#

i actually have a rough draft library based on https://www.youtube.com/watch?v=RqlnWv6NZos

โ€”
In this talk, Scott will look at an unusual approach to designing internal interfaces and external APIs โ€” a "capability-based" approach that takes the Principle Of Least Authority and applies it to software design. When this approach is used, it produces a robust and modular design that captures the domain constraints, resulting in an API that...

โ–ถ Play video
#

which isn't quite the same as DI but i found it very appealing

ember maple
pearl cliff
#

i'll probably never finish it because i'm back to doing data science and i definitely don't want to go back to web dev. no need for this stuff in my field now.

proud nebula
#

Writing a simple DI isn't that bad

#

I wrote a clone of pytests fixtures DI stuff for hammett.. It wasn't THAT bad

ember maple
viscid basalt
# ember maple A todomvc style di is easy, but then come the layers of breaking points as thing...
import asyncio
import contextlib
from contextlib import aclosing

import httpx
from aioinject import Container, Singleton, Callable


@contextlib.asynccontextmanager
async def httpx_transport() -> httpx.AsyncBaseTransport:
    async with httpx.AsyncHTTPTransport() as transport:
        yield transport
        print(f"{transport=}")


@contextlib.asynccontextmanager
async def github_client(transport: httpx.AsyncBaseTransport) -> httpx.AsyncClient:
    async with httpx.AsyncClient(base_url="https://github.com",
                      transport=transport) as client:
        yield client
        print(f"{client=}")


class Service:
    def __init__(self, client: httpx.AsyncClient):
        print(client)


container = Container()
container.register(Singleton(httpx_transport))
container.register(Callable(github_client))
container.register(Callable(Service))


async def main() -> None:
    async with aclosing(container):
        async with container.context() as ctx:
            print(await ctx.resolve(Service))
        # scoped dependencies are destroyed (github_client)
    # singleton dependencies are destroyed (httpx transport)


if __name__ == "__main__":
    asyncio.run(main())

๐Ÿค”

proud nebula
viscid basalt
viscid basalt
pearl cliff
#

surely fastapi is just using exitstack... right?

#

i don't want to look

viscid basalt
#

Me too ๐Ÿ˜›

ember maple
#

I'm out of this

pearl cliff
#

maybe this is such an alien concept in python because people don't write python applications big enough to justify complicated DI frameworks?

proud nebula
#

The devil is always in the details. And sometimes that devil will be quite bad for performance.

viscid basalt
proud nebula
#

(dry lines)

pearl cliff
#

ok, i think i see what that's doing... this isn't like fastapi, it's making these dependencies available anywhere in the code? container.wire(modules=[__name__])

viscid basalt
pearl cliff
#
#

this example from that doc looks like what i usually write:

import os


class ApiClient:

    def __init__(self, api_key: str, timeout: int) -> None:
        self.api_key = api_key  # <-- dependency is injected
        self.timeout = timeout  # <-- dependency is injected


class Service:

    def __init__(self, api_client: ApiClient) -> None:
        self.api_client = api_client  # <-- dependency is injected


def main(service: Service) -> None:  # <-- dependency is injected
    ...


if __name__ == "__main__":
    main(
        service=Service(
            api_client=ApiClient(
                api_key=os.getenv("API_KEY"),
                timeout=int(os.getenv("TIMEOUT")),
            ),
        ),
    )
viscid basalt
#
container = Container()
container.register(Singleton(httpx_transport))
container.register(Callable(github_client))
container.register(Callable(Service))

Becomes

class Container:
    transport = providers.Singleton(httpx_tranpsport)
    gh_client = providers.Factory(github_client, transport=transport)
    service = providers.Factory(Service, client=gh_client)

and it's a pretty simple case too

#

I have a container with 156 dependencies at work ๐Ÿ‘€

pearl cliff
#

you all are working on much bigger applications than i am ๐Ÿ˜†

viscid basalt
#

156 is not that many, but it's not small either

#

As of testing I generally just need to override my db session ๐Ÿค”

#

And any other external dependencies I may have, like caching if I use it

proud nebula
pearl cliff
proud nebula
#

actually.. that sounds way too much

proud nebula
#

honestly this number sounds way too big... I've only been at this for less than 3 years

viscid basalt
#

This could even be done without DI

#

As I said - just session_factory.configure(bind=new_url)

viscid basalt
#

To be honest a lot of these are pydantic models

proud nebula
#

wth.. iommi is 32k

#

that's a LOT of tests though

#

django 294k.. that sounds a lot. I am starting to wonder about this tool I'm using honestly ๐Ÿ˜…

#

ooh, hah, I have 10kloc in migrations for my main app

viscid basalt
#

I don't think I can develop without DI at this moment, I need to work on better testing support of my library though, because some kind of dependencies are a bit annoying to work with

sacred depot
#

How do you test the error message accompanying an exception?

#

(note: using pytest if that matters at all)

proud nebula
lament heath
#

I use it all the time in "with insert_pytest_raises()" in "better-devtools". It's similar to "insert_assert" from devtools but for exceptions.

maiden pawn
sacred depot
#

(although in this case I could do without the first test, admittedly)

maiden pawn
# sacred depot ```python def add_torque_spec(self, rpm: int, factor: float): ...

^^^ I don't see myself create an exception for every value of rpm that is wrong :p

i actually can.

exc.py

class LessThanZeroExc(ValueError)
  pass

class RPMLessThanLastEntryExc(ValueError)
  pass

app.py

from . import exc

        def add_torque_spec(self, rpm: int, factor: float):
            if rpm < 0:
                raise exc.LessThanZeroExc("rpm cannot be less than 0")
            if rpm <= self._last_rpm:
                raise exc.RPMLessThanLastEntryExc(f"specified rpm ({rpm}) is not strictly greater than last entry ({self._last_rpm})")
#

because it makes typed unit testing without checking strings.

#

and easy refactoring.

#

and potentially can be just removing fully string explanations into custom exception init

sacred depot
#

You can just pass like that and it inherits the constructor of the parent class??

#

Also I didn't know you could import ., good to know

#

Err, from . import, I mean

maiden pawn
#

sometimes i define actually __init__ for creating more custom msgs in them ๐Ÿ˜…

maiden pawn
# sacred depot Also I didn't know you could `import .`, good to know

it will work if they are in same module, that has __init__.py file in it
and application was launched... with ensured that absolute path of the app starts... before this module (u don't have entrypoint script in this folder/module)

custom_module/
  __init__.py
  exc.py
  app.py

app_module/
  __main__.py
entrypoint.py

launching as python3 -m app_module
or as python3 entrypoint.py and etc
then relative import in all other modules (including custom_module) works fine

#

technically entrypoint can be even in same custom_module though

custom_module/
  __init__.py
  exc.py
  __main__.py
  app.py

as long as it was launched as python3 -m custom_module or as python3 -m custom_module.__main__ in a way that ensured root folder of python module paths... is at the parent folder

sacred depot
#

This is getting a little over my head for the moment, since I'm not at that level yet :p

sacred depot
#

OK, I am having a look at hamcrest

#

I find it strange that it uses for instance assert_that(someDict, has_key(someKey)) instead of assertThat(someDict).has_key(someKey))

#

Oops, too used to assertj

#

(and Java -- I use camelKey too much)

#

Speaking of which, how do you test that a dict actually has an existing key without hamcrest?

maiden pawn
#

dictionaries are bad = full of magical keys and values (unless you are able to do strict typing in newest verisons, but even that is not fullproof)

sacred depot
#

Depends on what you call "newer versions" -- the project I'm on uses 3.11

maiden pawn
#
class YourStruct(BaseModel):
  requried_key: int

with pydantic

maiden pawn
#

use pydantic ๐Ÿ˜Š

sacred depot
#

mypy -- again something I'm unaware about :)

#

Are those static type checkers?

maiden pawn
#

yeah it is type checker, turning a bit dynamic typing into more static typing

sacred depot
#

But not having that "safety net" that is compile-time type checking is still making me uncomfortable

#

I must get used to it...

maiden pawn
#

there is no reason to write bad code if u can write quality code

#

your future you will thank you (in a week, or month, or a year)

sacred depot
maiden pawn
#

aww

sacred depot
#

I was brought in because of my knowledge of physics, I knew nothing about python when I started not even three weeks ago :p

maiden pawn
sacred depot
#

I have done Java for a double digit number of years now, and while it helps me in some aspects, it does me a disservice in others

#

I'm like the donkey from Buridan at the moment when it comes to writing python :p

maiden pawn
sacred depot
#
>>> a = 1
>>> b = 1
>>> a is b
True
>>> a = 20000000
>>> b = 20000000
>>> a is b
False
#

So, python does behave like Java a little in this regard

#

(but this becomes offtopic for that channel)

#

Eh, that reminds me when I submitted the code for Java's Path assertions for assertj... I really don't get why hamcrest does not use that syntax

pearl cliff
#

it can be somewhat liberating in terms of program structure to be able to separate your representation of data from operations on data, reserving classes for the subset of times when you really want both simultaneously

sacred depot
#

So, this is a strange dichotomy, really

pearl cliff
#

in python whether something is "primitive" is somewhat of an implementation detail

#

it's actually kind of a nice characteristic of the language imo

sacred depot
#

You can still stuff everything into a single class even in Java, but... Uh, no

pearl cliff
#

(from the user perspective, not so great for performance)

sacred depot
#

Even in Python I won't do that

#

Well, a single file in python that is

#

Actually you're limited to 2^31 - 1 chars in a source file in Java

#

But, uh...

#

Anyway, what I was talking about is that I was surprised hamcrest chose to assert_that(x, has(y)) instead of assert_that(something).has(y) for instance

#

That makes the syntax rather awkward to my "trained" assertj mind

maiden pawn
#

If we would be not knowing about deserializers
Not using Django Rest framework serializers
And not using pydantic to deserialize custom code

We would have resorted to such check

sacred depot
#

I don't like accessing "instance variables" like that but it works...

pearl cliff
sacred depot
#

(fluent interfaces, that is)

pearl cliff
#

actually that particular example i think is really nice and would belong in a python codebase imo

#

but other cases like FooFactory().set_option("q", 1).build_foo() are not typical, because you can just pass optional keyword args instead

sacred depot
#

Even with lambdas you can have *args, **kwargs... That is something very new to me. I resent using those for now due to my lack of experience

#

I have enough trouble already doing "base python"...

pearl cliff
river pilot
pearl cliff
viscid basalt
#

I mostly write/work with web applications and would avoid using kwargs or dict unpacking in general where other devs would prefer it, e.g.:

def create_something(self, **kwargs) -> Something:
    model = Something(**kwargs)
    self._session.add(model)
    return model
#

I would usually write

def create_something(self, dto: SomethingCraeteDTO) -> Something:
    model = Something(title=dto.title, description=dto.description)
    self._session.add(model)
    return model
#

Not only it's more descriptive but is more type safe too, you could do something like Something(**dto) but then it's really not different from the first option

proud nebula
ember maple
#

higher kinded types are missing

def create_something(self, kwargs: Unpack(Initargs(Something)]) -> Something:
   ...
sacred depot
#

I'm not sure how I feel about the discussion at hand wrt typing since I come from a very strongly typed language (well, except for primitive types)

#

But since I do have a lot of experience with Java, if you have questions about how Java does this and that wrt typing, I can try and answer

#

I'll be as descriptive as possible, and unbiased

#

That is, if you need my input at all -- I'm anything but an authority on the subject after all

hollow basin
#

@sick shell if you're currently using the unittest library that comes with Python, you might consider switching to pytest. It is (ironically) a lot more pythonic than unittest

drifting sorrel
# viscid basalt Not only it's more descriptive but is more type safe too, you could do something...

One thing that I like with the **kwargs style (or passing in a dict) is that the create_something function doesn't need to be aware of the details of the passed in data, if it is only passing data on to other functions or classes. Also, the function can be re-used in other scenarios that might not fit that DTO instance. Sometimes, custom built types will lock-in code into one single use case and that could lead to code duplication - or even worse: complex OOP hiearchies of DTOs.

viscid basalt
#

Also why would you assume DTOs would have any inheritance at all

drifting sorrel
#

I would say it is common that DTOs inherit from a "base" or even several more generic DTOs ๐Ÿ™ˆ

Your example is a function that is specific, yes. But in other cases you might want some flexibility with the input data to be able to reuse functions without forcing everything to be in a specific data format. That's when the "bases" usually enter the scene, you want to reuse a function but the data is only a subset of the original DTO ๐Ÿ˜„

molten escarp
#

Hello everyone! I just updated a library I released earlier this year, megamock. It improves the developer experience for using mocks by letting you quickly create spec'ed mocks from references and patch things by passing them in instead of using path strings, among other things.

In addition to updating the library, I've created a custom GPT for assisting you with using the library. The GPT has been coached on how to generate the tests via a step-by-step process and I'm curious if this is helpful for anyone. Creating tests that use mocks isn't a requirement for finding it to be helpful.

The github repo is here, and has everything, including the GPT prompts and data: https://github.com/JamesHutchison/megamock

maiden pawn
viscid basalt
maiden pawn
#

that is just rude (to my time) to answer with ChatGPT.

bitter wadiBOT
#

10. Do not copy and paste answers from ChatGPT or similar AI tools.

vernal juniper
#

Hello peeps!
Is there a way of testing something that has multiple functions (which receive HTML data) without actually having to write test HTML?
It wouldn't be a problem, except it is a plugin architecture thingy, so every time you add a plugin you have to write HTML to test it. Is there a way to automate this somehow?

maiden pawn
#

From where they get it

#

And what is nature of the function. What it does to html

vernal juniper
#

Different websites tbh
Each function is a handler for one website
Like, I know that it seems daunting considering that, but I also know that some bs4 magic exists that at least makes it easier to do so

The functions just scrape data tbh

maiden pawn
#

On first run u get and save real data u reuse then for tests.
Any moment u can delete saved cache to regenerate it

#

There is even library for this to automate such stuff a bit more (caching requests for tests)

vernal juniper
#

That is a good idea
Just have to make sure to add the downloaded HTMLs to gitignore lmao, for copyright reasons lmao

maiden pawn
vernal juniper
vernal juniper
maiden pawn
vernal juniper
#

Oh, thank

#

Hopefully these "Uber" people or whatever make trustworthy libraries
Never heard of em

maiden pawn
maiden pawn
vernal juniper
#

Yeah I saw it.

#

Looking into vcrpy

maiden pawn
vernal juniper
#

Would you look at that
Seems like one of the websites I scrape is currently broken lmao
I would have benefitted greatly from vcrpy now lol

wet olive
#

hey guys, how do i get code coverage to work in pycharm community edition? i'm using the coverage library, and upon running python -m coverage run --source= test/ -m unittest discover -s test/ where test/ is the directory for my tests, it tells me Can't find '__main__' module in 'test/'

river pilot
#

Do the tests run without coverage? python -m unittest discover -s test/ ?

wet olive
#

no, it runs 0 tests, even though i have 7 defined in test/class_test.py

#

rn, i am manually using the pycharm run button to run them

wet olive
#

ohhh, am i meant to make my tests in a unittest class....

river pilot
#

unittest requires classes, yes. You can switch to pytest if you want to use functions. But I'm concerned that the behavior is different with coverage and without. They should be the same.

wet olive
#

i changed it to be in the unittest class, and now it seems to work when i run python -m coverage run test/class_test.py
however, it doesnt run when i do python -m coverage run --source= test -m unittest discover -s test

wet olive
river pilot
wet olive
#

that i added a space n --source= test

river pilot
#

oh! right

wet olive
#

removing the space it runs 0 tests

wet olive
river pilot
#

your file should be named test/test_class.py

wet olive
#

it is

#

i was wrong. it was named class_test.py

#

its fixed now. thank you very much

drifting sorrel
pearl cliff
#

like all design patterns, it's a useful idiom but maybe not worth explicitly building your software around it

storm leaf
#

how do i get ready for test

hexed cloak
storm leaf
#

For college

fallen otter
#

Hi Python testers! I wanted to share a new project that might be useful for you. I write a lot of python command line tools and usually use the Click framework which provides an excellent CliRunner test helper to test the command line script. Sometimes I don't use Click (when I don't want an extra dependency) and use argparse instead. In those cases, I really missed being able to use CliRunner so I ported the Click CliRunner to work with argparse (or manual sys.argv parsing) apps: https://github.com/RhetTbull/clirunner

GitHub

A python test helper for invoking and testing command line interfaces (CLIs) based on Click's CliRunner - GitHub - RhetTbull/clirunner: A python test helper for invoking and testing command...

proud nebula
storm leaf
#

Oh I thought it meant unit test

proud nebula
storm leaf
#

Ok sorry I'm still new lol

proud nebula
#

Np

leaden venture
#

Hi guys, a few days ago I wrote a message in #web-development regarding my new drf-api-action project
https://github.com/Ori-Roza/drf-api-action
I struggled to make it understandable for developers and I thought it might be helpful to ask for your opinion.
@proud nebula helped me to figure that my package is great for testing Django Rest Framework web servers by treating REST methods like regular functions.
for example:

"""python
class DummyView(APIRestMixin, ModelViewSet):
queryset = DummyModel.objects.all()
serializer_class = DummySerializer

@action_api(detail=True, methods=["get"], serializer_class=DummySerializer)
def dummy(self, request, **kwargs):
    serializer = self.get_serializer(instance=self.get_object())
    return Response(data=serializer.data, status=status.HTTP_200_OK)

def test_dummy():
api = DummyView()
result = api.dummy(pk=1)
assert result['dummy_int'] == 1
"""

so first, I want to say thanks to this amazing community, and I'll be more than happy to invite you to use this package let me know what you think ๐Ÿ™‚

GitHub

Obtaining DRF benefits for making API Python packages & testing REST methods - GitHub - Ori-Roza/drf-api-action: Obtaining DRF benefits for making API Python packages & testing REST methods

crisp trail
#

I made an game of Leap Frog for no real reason, but it seems to be running slow. Does the IF statement slow loops down that much?


print('Welcome to your eternal punishment! Lets play some leapfrog!')

jumper_1 = input("Who's the first to jump?\n")
jumper_2 = input("Who will be getting jumped over\n")
y = 0
z = 0

while y == 0:
if z == 0:
print(f'{jumper_1} jumped over {jumper_2}!')
z += 1
print(f'then {jumper_2} jumped over {jumper_1}!')
print(f'then {jumper_1} jumped over {jumper_2}!')

proud nebula
crisp trail
proud nebula
crisp trail
proud nebula
# crisp trail you may have been, but i'm very dumb

You asked if if is slow. In code that does a whole lot of print. Print is millions of times slower. So the question seems silly. Like asking how expensive a glass of water is when faced with an empty bank account, while at the same time buying multiple Porches.

crisp trail
ember maple
silk crescent
#

how can I use fixture to create a mock file of certain size?

#

I'm doing something like this

def test_collection_size(create_fake_file):
    files = [create_fake_file]
    size = get_collection_size(files)
    assert size == 32

create_fake_file fixture should return a mock file of size 32 bytes

river pilot
silk crescent
# river pilot it's hard to know how to help. where is the full code? What is going wrong?
def get_collection_size(file_list: list[Union[os.PathLike, str]]) -> int:
    """
    Calculates the cumulative size of the files in the provided list.

    Args:
        file_list (List[Union[os.PathLike, str]]): A list of file paths.

    Returns:
        int: The cumulative size of the files in bytes.
    """
    total_size = 0

    for file_path in file_list:
        if file_path:
            try:
                file_size = os.path.getsize(file_path)
                total_size += file_size
            except OSError:
                pass  # Ignore invalid file paths or inaccessible files

    return total_size
@pytest.fixture
def fake_file_content():
    # Returns 32 bytes of space
    return b" " * 32


@pytest.fixture
def create_fake_file(fake_file_content):
    def _create_fake_file(file_path):
        # Use unittest.mock.mock_open to create a mock file object
        mock_file = Mock(spec=open, read=Mock(return_value=fake_file_content))

        # Use unittest.mock.patch to replace the built-in open function with the mock_file
        with patch("builtins.open", mock_open(read_data=mock_file.read)):
            # Write the fake content to the specified file path
            with open(file_path, "wb") as file:
                file.write(fake_file_content)

    return _create_fake_file
#

I'm getting E TypeError: stat: path should be string, bytes, os.PathLike or integer, not function

river pilot
#

@silk crescent but i also wonder how this is meant to work: you are patching open with a function that doesn't make real files, then using os.path.getsize on the result.

silk crescent
#

isn't this possible ?

river pilot
silk crescent
#

I have to test if the function is getting the size of a file correctly

silk crescent
silk crescent
#

with another fixture ?

#

oh no if I make it a fixture then It will be called first before the assert

silk crescent
#
from pathlib import Path
PROJECT_PATH = Path(__file__).parent
DATA_FOLDER = PROJECT_PATH / "test_files"

@pytest.fixture(scope="session")
def create_fake_file(tmp_path_factory):
    # Create a temporary file in the tmp_path directory
    temp_file = tmp_path_factory.mktemp(DATA_FOLDER) / "temp_file.txt"

    # Write 32 bytes of data to the file
    temp_file.write_bytes(b"a" * 32)

    return temp_file

#

the directory already exists. is that the problem ?

#

ok I changed it to temp_file = tmp_path_factory.mktemp("temp") / "temp_file.txt" then It worked

hexed cloak
hexed cloak
sullen oar
#

how do I test a package that makes request.get calls but i want to just use a file that contains some small sample of data from the response? i dont even know how to google for this

river pilot
maiden pawn
# sullen oar how do I test a package that makes `request.get` calls but i want to just use a ...

it is called patching and mocking. (and the 3d case is actually called using a Spy, although often called Mocking too)

  1. U can utilize answer above requiring extra third party lib. (global affecting way + extra lib)
  2. Or u can just use from standard lib mocks and patches https://docs.python.org/3/library/unittest.mock.html , for patching specific lib or class or function (this choice will work with pretty much no code changes, we abuse here python flexibility. U will preferably need to move your code at least into separate method that returns simple values though)
with patch.object(SomeClass, 'class_method', return_value="insert return body of your request.get from file here"):
    SomeClass.class_method(3)
    mock_method.assert_called_with(3)
  1. Or u can just rearchitect your code to be accepting via compsition some kind of more abstract requester that can be replaced during testing with loading from local file thing (this choice requires code restructure to more unit testable code architecture)

P.S. last two choices do not require extra libs and not creating extra overhead for maintenance if u need it just once. Consider adding library only if u are really going to use it a lot.
P.P.S. choice #3 is more preferable if u are strict typing with mypy/pyright

#

i would have used as a semi lazy choice at least 2nd preferably probably.

native orbit
#

hello need a bit of help with pytests

#

i want to use pytest to verify this ValueError is being raised

#

but how can i pass in input to pytest.raises

#

if anyone has an answer please pm me because i doubt ill see the message after 30 minutes or so

sacred depot
#

You have a problem here

#

How do you differentiate between player 1 and 2 missing?

#

In your case you won't need the assertion, only the with, but here goes

swift pewter
hexed cloak
#

Probably how to make the calls to input return under test

#

So I think you'll need to mock out input

native orbit
native orbit
native orbit
hexed cloak
native orbit
hexed cloak
#

Best keep the messages in the chat

#

If you have a long thing to paste you can use

#

!paste

bitter wadiBOT
#
Pasting large amounts of code

If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.

ember maple
native orbit
#

The only parameter I want for the input is that it exists whether its numbers or strings

ember maple
#
def get_names(input=input):
#

Then you can pass in custom input functions for automated Tests

#

But it May be better ux to make a function that handles one player name correctly

It's a pain to have to re-enter the correct name again if the second one is broken

hexed cloak
#

Mocking input is fine here imho

sacred depot
#

OK, I have a class with a values instance variable which is normally a deque; I want to check whether its .appendleft() method has been called, using pytest

#

I know how do do this using python-mockito: you would when(instance.values).appendleft(...) and that would automatically mock the function to "do nothing", but what is the equivalent using pytest? I can't really make it out just by reading the docs...

#

Also, what I really want afterwards is to check whether the function has been called

#

Uuuh... E AttributeError: 'collections.deque' object attribute 'appendleft' is read-only

#

So you can actually make that?

#

I'm more than confused now

#

Well, I used mockito's .spy() instead and it works

#

And, uh, no it doesn't

#

OK, I'm in trouble here

hexed cloak
#

Can you just check where the value ended up?

sacred depot
#

I'll pastebin

native orbit
#

@hexed cloak

#

so far this is my testing

hexed cloak
native orbit
#

because any further implications either gives me an OSerror or a TypeError

native orbit
#

one sec

hexed cloak
sacred depot
#

I don't understand :(

#

Is it a conflict between pytest and python-mockito?

native orbit
#

!paste

bitter wadiBOT
#
Pasting large amounts of code

If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.

native orbit
#

um sorry idk how to use it

#

sorry just figured it out

hexed cloak
hexed cloak
#

Ok so what happens when you run the test?

native orbit
#

well yeah this is for cs50p and so thats why i need to verify the valueerror personally i wouldnt bother because it reprompts if no input and to me that works

hexed cloak
#

I don't know cs50p but I'd test every branch of my codebase

hexed cloak
native orbit
#

i get OSerror try using -s

sacred depot
hexed cloak
native orbit
native orbit
#

also again sorry for bothering you and huge thank you mate for helping me

hexed cloak
#

Perfect thanks for the traceback. It's good practise to show your code and full traceback first thing when asking for help

hexed cloak
#

So wrap your test in with mock.patch("scrabble.input") as mock_input:

native orbit
#

so i put that line of code under the test_get_names() and it should work?

hexed cloak
#

You'll also need to import mock

#

With from unittest import mock

sacred depot
#

sigh Even with pytest-mock I cannot make it work

hexed cloak
hexed cloak
sacred depot
#

OK, I don't get it, I'm going to post to the help channel, this is getting over my head

#

I've tried everything I can think of, nothing works

sacred depot
native orbit
#

okay so i installed mock library and imported it and its passing the test but im not sure exactly how or what is it testing

#

the code now

#

the traceback

hexed cloak
#

You don't need to install mock it comes with python now

#

It used to not that's why you can still install it

hexed cloak
#

pytest-cov is a good option

sacred depot
#

OK, I made it work

#

sigh

#
    def test_add_updates_deque(self):
        sample = 1.0
        mean_value = MeanValue()
        values = mock(deque)
        when(values).appendleft(sample)
        mean_value.values = values
        mean_value.add(sample)
        verify(values, times = 1).appendleft(sample)
#

I thought I could spy() over the values member of the created MeanValue instance but no

native orbit
#

I HAVE reached a middle ground

#

code

#

tester

#

@hexed cloak is this valid or am i wasting time and bad ux by making the ValueError raise an exception?

river pilot
#

I would write an example, but I don't understand what that test does. Does this actually call appendleft? when(values).appendleft(sample)

sacred depot
river pilot
sacred depot
river pilot
sacred depot
#

By testing this way I am sure of what is being called

river pilot
#

the important thing is that the deque is in the right state. You're tying yourself to implementation details.

sacred depot
river pilot
#

you will have another test that adds two values, and you can see that they are in the right places.

sacred depot
#

What I care about is that the oldest added value gets ejected when there's no room for it anymore

river pilot
sacred depot
#

And .appendleft() does that naturally for me

river pilot
#

you are testing the implementation. you can test just the behavior.

sacred depot
#

I agree, however testing that part of the implementation guarantees that the behaviour is what I want; I don't even need to test for what happens when too many elements are fed in

#

When using it I won't care

river pilot
#

sorry, you won't care about what?

sacred depot
#

About the implementation details; the behaviour is documented, and known to work, that is all that matters

river pilot
#

@sacred depot so I understand, what does this line do? when(values).appendleft(sample) It calls appendleft or it doesn't? If it doesn't, what does it do?

sacred depot
river pilot
sacred depot
river pilot
sacred depot
river pilot
#

i see.

sacred depot
#

Python's mockito differs from Java's in that sense

#

In Java you would doNothing().when(theObject.theMethod(...))

river pilot
sacred depot
#

But more often than not I mock interfaces, so this is not really a problem

#

I rarely "monkeypatch" real object instances

river pilot
#

how does the mock object get the full interface?

sacred depot
#

which means to be brief: you cannot mock a non existing method, that's a compile time error

sacred depot
#

Basically, if you have a Class<?> object, you can access all the methods in that object

#

Which is why you declare for instance that you want a final Foo foo = mock(Foo.class) <-- here, Foo.class is a Class<Foo> object (and, also, I use mock() directly here because I declared import static blablabla.mockito.mock, I don't remember the exact path, my IDE does that for me)

#

You can also mock() "real" instances (as long as the class is not final) but I try and avoid that whenever I can

sacred depot
#

raise TooMuchJavaError() :p

river pilot
#

it's clear we have different approaches to testing ๐Ÿ™‚

sacred depot
#

Which means we can learn from one another ;)

#

And I love that kind of interaction

#

(well, that is, if you learn anything from me)

#

Just to add to what I said, because I believe this is important: interfaces in Java are also Class<?> objects

#

Which is why you can mock() an interface -- the preferred way of mocking, really

river pilot
#

I'm familiar with Java (at least as of a few decades ago)

sacred depot
#

What I wanted to do with my test however was to spy values; but no cigar, I could not do it

#

And I don't understand why :/

#

Also, I wonder about the interaction of hamcrest with other testing frameworks such as unittest, pytest and python-mockito

#

Argument matchers are fascinating

#

Not to be overused, but when you need them, there is just no replacement

river pilot
#

i guess there's no reason it wouldn't work, it's just philosophically a different direction.

sacred depot
#

Philosophically?

#

It's not like hamcrest is a replacement for any of those, so...?

river pilot
#

But you can use hamcrest or other assertion functions in pytest if you want.

sacred depot
#

Ah, yeah

#

In fact hamcrest reminds me of assertj somewhat but... Well... I believe assertj is more powerful :p

#

In fact, and I will have to look that up, I wonder how python handles polymorphism

#

But that will be for later

#

sigh I hate being rate limited... I cannot include the full code into a post in the help channel :(

late robin
stable fjord
#

Hi all

#

Can u help in pytesting in python

hexed cloak
upbeat anchor
proud nebula
prisma rover
#

hi yall

#

my cmd is saying pip install isnt recogonized internal or external command

proud nebula
slow hill
#

Whatโ€™s a way to have a unit test catch when a class definition is updated but the serialization method hasnโ€™t been?

#

This just happened, which made a bug because when the data was deserialized back into the program, a bunch of essential data was missing causing the program to misbehave

#

By โ€œserializaitin method hasnโ€™t beenโ€ I mean that thereโ€™s basically a โ€œto_dictโ€ method that was not updated to reflect the new class members

#

My concern is that if I put a unit test and test for the serialzed string matching, then it will pass unless the test itself is updated which puts me back into the same boat because if I forget to update the dict method I sure as hell will forget to update the test

weary quarry
#

How complex is the serialization? Can you just reimplement a simpler version of it in the test, run both, compare the two?

proud nebula
slow hill
slow hill
# proud nebula I would first try to change the code so it doesn't misbehave but crash hard. If ...

So it doesn't crash hard, it just doesn't function properly. Basically what I'm saying is that I have a to_dict() method which takes and converts (serializes) the object into JSON, which is required because the objects aren't automatically JSON serializable out of the box. So, if I add another member or otherwise change that class, and I forget to also add the new member to the to_dict() method, then there is silent missing data from the JSON, and then that messes up the program when the data is deserialized on the next run, because there is missing data. Does that make sense? So my issue is that if I were to make a test for this, that test cannot have future modifications in it, which means that the same issue is present because if I or anyone else forgets to add the new member to to_dict(), then same could happen if we dont add it to the test.

river pilot
#

One way to test serialization is to find some tests that use one of these objects, and add a line near the top: obj = deserialize(serialize(obj)), and see if the tests still pass.

slow hill
#

Is there a way to compare the to_dict() method with some class metadata directly?

proud nebula
proud nebula
slow hill
#

I see... So I need to find away to enumerate the class attributes for this

#

I misunderstood your initial message and got it the other way around @proud nebula

proud nebula
river pilot
slow hill
#

The flaw here might be that my to_dict() relies on me manually updating it.

#

I wonder if I could use self.__dict__ instead, but not sure how it would handle that case above with the list of other class

upbeat anchor
#

this is the error

#

i tried reinstalling mysql

upbeat anchor
lament heath
#

Currently, my test job in github actions looks like this:

jobs:
  Tests:
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.10", "3.11"]
        poetry-version: ["1.2.2"]
        os: [ubuntu-latest, macos-latest, windows-latest]
        pydantic-version: [1, 2]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install poetry
        uses: abatilo/actions-poetry@v2
        with:
          poetry-version: ${{ matrix.poetry-version }}
      - name: Install dependencies
        run: poetry add "pydantic@^${{ matrix.pydantic-version }}.0.0" && poetry install --all-extras
      - name: Test
        run: make test
      - name: Upload coverage
        uses: codecov/codecov-action@v3

So I test on three operating systems, two versions of pydantic, and two versions of Python. However, this produces 12 jobs total. Each job installs its own poetry, packages, etc. What optimizations would you recommend here?

kind meadow
#

Sorry, I mean you can cache them. But you cannot share the cache between jobs

#

Have a look at the "cache" action

lament heath
#

I feel like it could be solved with tox. Maybe it has the ability to share portions of packages between python versions or something.

river pilot
#

I'm also curious what actions-poetry does beyond pip install poetry

lament heath
# river pilot do you need to test with both versions of pydantic? Is this a library you're bui...

I do need to test with both versions of pydantic because I support both of them and they are vastly different in some important parts of the functionality that I touch. Thanks for the tip about the poetry version!

Is this a library you're building?
I have built a pretty great API versioning framework that we already actively use at my work. It's pretty amazing and complex but solves a lot of tough problems. Right now I'm planning to publish an article about it and try to expose it to wider audiences which is why I want to support both pydantic versions.

https://github.com/zmievsa/cadwyn The link if you are interested

GitHub

Modern Stripe-like API versioning in FastAPI. Contribute to zmievsa/cadwyn development by creating an account on GitHub.

maiden pawn
lament heath
lament heath
#

Please, read my message. These jobs all have no dependencies. Outside of pydantic 1/2, all of them are very different.

maiden pawn
#

Difficult a bit to cache, since your libraries secondary deps could be updated

#

Essentially u have no option to cache without having loss of Ci quality

#

Hmm

lament heath
#

That's precisely what I'm asking, yes: whether I can cache something without significantly losing in quality.

maiden pawn
#

As an option I can see only running CI fully for single set of vars.
Cache for other cases

lament heath
#

So not running the jobs at all?

#

I have three platforms and two python versions. What do you propose to cache?

maiden pawn
#

Not really important speed up though

#

It is not like it takes too much time to install it

#

May be just don't optimize ๐Ÿ˜‰

lament heath
#

This will yield the same number of jobs and we will still install packages 12 times.

maiden pawn
lament heath
maiden pawn
lament heath
#

I appreciate the attempt but you are trying to explain the very basics. I understand this. I also have read the docu and I know which triggers github actions have. Now I am hoping to receive guidance from testing experts such as @river pilot and @proud nebula who might have other ideas and tools in their mind that could help me here.

silk crescent
#

how can we run multiple python version tests like we run in github ci/cd but locally ?

#

not like than act

pearl cliff
silk crescent
pearl cliff
silk crescent
#

I have multiple python installed & can use nox or tox ?

pearl cliff
#

i haven't used poetry in several years, so i wouldn't know. you'd have to browse or search their documentation. but i know several people here do use poetry so maybe someone can attest.

pearl cliff
silk crescent
#

other than the fact that nox usese a .py file as config ?

pearl cliff
silk crescent
pearl cliff
proud nebula
silk crescent
silk crescent
#

1 thing related to setting up pipelines in a project. I have some integration tests which takes hours to run should I run them in github actions ?

#

or just run the unit tests

proud nebula
silk crescent
proud nebula
#

Hours in computer time is crazy.

silk crescent
#

it spins up some docker container & copies the ethereum blockchain to setup some mock transactions so it's pretty time consuming

silk crescent
#

1 way would be to cache the result of the first test which will reduce down the time to 1-2 mins

#

so the data looks like this

#
{
    "BEE_POSTAGE": "061dfc1fc656410f1901e06f5b413039a6923e2747ca7d8cfe23391cd7b86c20",
    "BEE_PEER_POSTAGE": "e032d8ddc7227d0d6c4d0f87db16027924216afd0c00012884ba7af835b4a7c7"
}

for each new node the data changes.these are valid for 1 node & for the tests I need only 1 node so have to cache them somehow. can we do that using fixtures ?

#

I did something like this

@pytest.fixture
def read_local_bee_peer_stamp() -> str:
    with open(BEE_DATA_FILE) as f:
        stamp = json.loads(f.read())
    if stamp["BEE_PEER_POSTAGE"]:
        return stamp["BEE_PEER_POSTAGE"]
    return False

then calling it in

@pytest.fixture
def get_peer_debug_postage(printer, read_local_bee_peer_stamp, bee_peer_debug_ky_options) -> BatchId:
    stamp: BatchId

    if read_local_bee_peer_stamp:
        return read_local_bee_peer_stamp
#

but for some reason they don't seem to return the data from the stamp file

#

idk know why

weary quarry
#

Your first fixture is marked as returning a str but you have a path that returns False. If you returned False from it your second fixture will return None.
Is that what is happening?

silk crescent
maiden pawn
#

!rule 6 , stop cross posting and advertising ๐Ÿ˜…

bitter wadiBOT
#

6. Do not post unapproved advertising.

pearl cliff
#

are there any good books/articles/etc that talk about strategies for testing complicated control flow and/or a large number of possible valid states?

i find myself needing to do this a lot, either adding tests to untested legacy code, or testing performance-sensitive code that's difficult to refactor, especially with numpy/pandas/polars operations that tend to benefit from doing more things at once.

i like to think i have a fair amount of experience with it by now, but i also feel like it's the hardest programming-related thing i have to do on a regular basis. so i think it would be useful to see how other people approach this task.

#

i suppose the best way to test something like a state machine is to test every possible transition separately. but sometimes even enumerating all those possible transitions can be tricky

silk crescent
#

I'm trying to make temp files using fixtures like this

@pytest.fixture(scope="session")
def create_blank_temp_files(tmp_path_factory):
    # Create a temporary directory
    temp_dir = tmp_path_factory.mktemp("temp")

    # Create 2-3 temporary files in the temporary directory
    temp_files = [temp_dir / f"temp_file_{i}.txt" for i in range(2, 5)]

    return temp_files

but Pathlib.is_file() is returning False

proud nebula
silk crescent
silk crescent
proud nebula
silk crescent
#

& then for each file I'm doing is_file()

proud nebula
#

Your fixture is called create_blank_temp_files which it doesn't do. return temp_files is a lie

silk crescent
proud nebula
silk crescent
proud nebula
silk crescent
# proud nebula It's a lie because it's a list of paths. To files that don't exist.
def _make_filepath(file: Union[os.PathLike, str, Path]) -> str:
    """
    Extracts the filename from the provided file path.

    Args:
        file (Union[os.PathLike, str, Path]): The file path.

    Returns:
        str: The extracted filename.
    """
    if isinstance(file, str):
        file = Path(file)
    if file.is_file():
        return file.name

    msg = f"Invalid file path: {file}"
    raise TypeError(msg)
for file_path in file_list:
        if file_path:
            filename = _make_filepath(file_path)

I'm doing this

proud nebula
#

Think of it like this. If I make up a name like "John Andersson", an entire human being doesn't pop into existance. Just because there's a name, doesn't mean there's a person. Same with files and file NAMES.

#

You have created file NAMES. But there is no FILE.

silk crescent
proud nebula
reef night
#

Hey, between unittest and pytest, which is considered โ€œbest practicesโ€?

pearl cliff
maiden pawn
#

it takes theory of testing

  • getting to know manipulating code architecture
    in order to understand best practices
#

technology itself is not able to be best practices, people are able to screw up any framework equally

clever viper
#

I'm trying to mock a mysql.connector interface and running into an issue. I'm using MagickMock and patch, and on the one hand, I can tell those are actually working. However, when I assert_called_once on the mock object, the test fails.

My debugging shows that it is, in fact, being called. Not sure what I'm missing here.

    @mock.patch('my_module.mysql.connector.connect')
    def test_fetch_user_sms(self, mock_db_connect):
        sms = '+1234567890'
        mock_cursor = mock.MagicMock(name='mock_cursor')
        mock_cursor.fetchOne.return_value = (sms,)
        mock_db = mock.MagicMock(name='mock_db')
        mock_db.cursor.return_value = mock_cursor
        mock_db_connect.return_value = mock_db

        email = 'john.doe@example.com'
        result = my_module.fetch_user_sms(email)

        mock_db.cursor.assert_called_once()
        mock_cursor.execute.assert_called_once_with('''
            SELECT phone
              FROM account
             WHERE email = %(email)s
               AND phone_is_valid
        ''', {
            'email': email,
        })
        self.assertEqual(result, sms)
maiden pawn
#

docker-compose up mysql with forwarded ports and u get clean mysql with necessary version for local test executions

#

we can arrange it as full docker run command if desired

#

mocking db is rather dangerous practice of having a lot of unecessary testing code. dereasing testing code quality.

#

u can mock in a good way, with mocking data (pydantic) structures received from another module. that is a right way

clever viper
#

I'm well versed with docker, just need to get an export of the prod db structure (not my DB, external service's DB who apparently can't be bothered to give the needed encrypted SMSes over their REST API)

#

so their solution was to give a Read Only replica DB o.O

maiden pawn
clever viper
#

This is an external service, as in, system we integrate with, not even ours. I'm not remotely close to calling those shots for them ๐Ÿ˜

maiden pawn
clever viper
#

yep, all I really need is a table named "account", with columns named "phone" and "email"

maiden pawn
clever viper
#

I was trying to use Mock for this, to learn Mock, but you are right, it's probably the wrong situation to use it in

#

Thanks! Also, love the Darkwing duck reference ๐Ÿ˜‰ big fan, hits right in the childhood

sick widget
#

Hey people. I am struggling with something for a couple of days now. Can you take a look? It's an inheritance issue:https://stackoverflow.com/questions/77684533/how-can-i-modify-the-python-unittest-setupclass-method-of-a-child-class-without

proud nebula
#

You probably need to describe what you're actually trying to do, instead of your idea of a solution.

#

xy problem...

sick widget
#

Sure. Did you read the description? I can elaborate on the parts that you think are not clear.

proud nebula
#

Yea, you're avoiding to describe the real situation though.

#

You've abstracted it so much, so we have no idea if your idea of a solution is crazy or smart.

sick widget
#

Alright. I'll try to explain step by step. Please let me know which parts are too abstract.

#

I am writing some unit tests for a function of a module. This function needs to be tested against multiple input sources. So, I thought I could create one test class (the parent class), and then inherit the test cases from there for every other test class that will be used to provide different input sources.
The test methods are only 3 but I want to create 3 more classes that will run the exact same test, only with different class properties

proud nebula
#

Sounds like you should either use a parametrized test in pytest, or just write some functions.

sick widget
#

The class properties are defined in my parent class in the setUpClass method. In every other child class, I want to overide the class properties with the NEW class properties, because the tests are written in a way to receive the class properties as input

#

I cannot use other libraries than unittest. I need to find a way to do this here.

proud nebula
#

Cannot? hmm.. that sounds weird.

#

Anyway, what's wrong with just some functions?

sick widget
#

I have to use unittest because it's the module used by my company for a testing framework that is built for multiple teams.

proud nebula
#

You should try to fix that heh. But yea, not right now.

sick widget
#

So, back to the problem.. Why does the child's setUpClass overide the parent's setUpClass? Why isn't it executed lineraly? Start with class 1, set it up, run the tests, go on to the next, etc.

proud nebula
#

You want to run some code, but sometimes you need some input to be X, sometimes Y. This sounds like you want just some functions.

proud nebula
sick widget
#

I ran the snippet I sent with a debugger, and when the interpreter reaches the first test case, the class properties are modified according to the child's setUpClass method ๐Ÿ˜ฆ . If this is not what's happening, can you explain how it works?

proud nebula
#

Again: WHY? You haven't answered this. What's wrong with reusing the code with just some plain old functions?

sick widget
#

I don't want to repeat the code in every class. Do you mean calling other functions than the setUpClass method?

proud nebula
sick widget
#

Could you explain with an example how I could re-use the tests written once multiple times in Unittest? I am not sure if I am following.

proud nebula
#

I don't think you should reuse the tests. I think you should write functions.

maiden pawn
proud nebula
#
def test_x():
   a()
   b()
   c()
   d(1)
   assert something

def test_7():
   a()
   b()
   c()
   d(2)
   assert something

is better as

def foo(x):
   a()
   b()
   c()
   d(x)

def test_x():
   foo(1)
   assert something

def test_7():
    foo(2)
    assert something
#

It sounds to me like you are stuck in a mental track of thinking of it as "reusing tests" but you could instead think "a test is just normal python" and then make functions

maiden pawn
proud nebula
maiden pawn
#

๐Ÿค” in python it can be Fixture Or Function, depending on the need

#

Pytest Fixtures are a bit more preferable over functions, due to them being more explicitely..... testing code
and having control how much they should be reused per test. (saving some performance from recreating them)

proud nebula
#

You're distracting from the problem again Darkwind

sick widget
#

There were some solutions that proposed to create another class with all the tests and inherit that instead but it seems that it creates the same issues. Simple writting a function doesn't seem like a good option for what I need to do. Thanks anyway.

proud nebula
#

You get the help you enable. You haven't let us help so ๐Ÿคทโ€โ™‚๏ธ

sick widget
#

But I've shared the stackoverflow url. There is a snippet there that describes a very simple example.

#

I really ain't doing something more complicated than that.. I need to make sure that the property defined in the parent class won't get modified by the children's setUpClass method before the test runs for the parent class first.

#

that's it

lament heath
proud nebula
proud nebula
# sick widget that's it

No, it's not. That's you being mentally stuck because you've made up your mind about the direction you are going.

naive heart
#

quick question if I had a function(A) and every other function(B,C,E,F) uses it, do I really need to do testing on A?

def A(num, foo=1):
  return (num*2)+foo

def B(num):
  return A(num, foo=2)

def C(num):
  return A(num, foo=3)

...
west grove
naive heart
west grove
proud nebula
naive heart
#

sorry for the poor English

proud nebula
naive heart
dense bough
#

I feel the opposite would be justified. Test A extensively because it holds the actually implementation. And then minimally for the rest for coverage.

proud nebula
#

Yea, I think I agree with that.

#

A is a good target for mutation testing...

naive heart
#

than I would need to list of all the possible foos values, than loop over

proud nebula
#

You can use property based testing to find them... but honestly I think mutation testing is easier and faster.

naive heart
#

oh i see

#

thanks again

ember maple
naive heart
ember maple
#

you turned a file reading example into a math example

#

also wat does the size repressent?

naive heart
ember maple
# naive heart size repressent foo

i mean is it a magic number, a size of a data field, something dynamic - the names you gave stuff make it a drunk guessing game, and i do'nt play those

naive heart
#

I am sorry for not making it clear. what about I give you the project idea?

ember maple
#

a rough outline may help understanding a bit

naive heart
# ember maple a rough outline may help understanding a bit

function A repressent read_ctype function which take ctype and bytes converting it to a ctype/python-type value and return, and functions(B, C, D, etc) the others are just read_int, read_char, so on, the differents between those functions are just one variable which at the end would be an int(the sizeof the ctype)

#

saving data as bytes in python without dumping python object using pickle

ember maple
#

sounds like the struct module

naive heart
#

oh yeah, it is

ember maple
naive heart
ember maple
naive heart
ember maple
#

and it wasnt the end goal (which you left out)

naive heart
#

oh, now I get what you mean, but thanks

ember maple
# naive heart oh, now I get what you mean, but thanks

now - whats the actual goal you have with the software, it may easily be possible that there are numerous libraries that get you 80% of the way with much higher performance/reliability than something fresh homegrown

#

(a key mistake all of us to way too often is reinventing wheels, but wobbly)

naive heart
#

what I'm saying wheel come in colors and shapes, the best is out there but sometimes you want to learn how they work

ember maple
#

yes, but you dont need to make the universe for each apple pie you want to make

its easy to make load of wobbly ruins when ignoring preexisting tools too much - its always a question of what you you want to get done

#

aka a wheel collection is not of help if a complete waggon is needed

naive heart
#

Definitely. I would need to go now, to finish this project

lament heath
visual atlas
#

does anyone know how to test a function which executes sql queries

#

an example will be appreciated

proud nebula
lament heath
# proud nebula I don't really buy that dogma. If it's code that you need to make sure it behave...

Sounds like a dangerous approach in the wrong hands. I have seen people make their projects incredibly hard to change by testing too much of the private interface.

I mean, I agree that when you are the only developer โ€” you can do whatever fits. But if you have middle and especially junior devs around you โ€” dogmas like that one can save the project. Or do you have an alternative way of keeping the fragility of the tests low?

proud nebula
#

Only testing the public surface in a web app would lead to you doing all tests with selenium. That's madness. So clearly that thinking can't be taken to the extreme.

lament heath
#

You can, yes. But you gotta somehow teach less experienced programmers to test well so having blanket rules does not feel too bad.

It's like "having more coverage is generally better than having less coverage".

How do you make sure that the quality of tests is high even when you are not looking? :)

lament heath
proud nebula
#

More mob programming with the juniors is a good idea.

lament heath
#

Let's say there are 4 teams of 4-6 backend developers within the company, 30% of developers write really poor tests and 50% of developers write more or less ok tests but with a large number of issues that could be corrected with a good review.

How would you review everyone in the company? :)

And that's a "good situation" example. Most teams I worked at do not write tests at all or write completely useless tests that barely check anything and never really run.

proud nebula
lament heath
proud nebula
lament heath
pearl cliff
proud nebula
#

Sometimes you can raise the bar and mgmt will follow. I did that at my previous job.

maiden pawn
pearl cliff
#

unless you can explicitly get management to agree with scheduling in time to add tests to legacy code, and add tests for new code, you're going to be putting in extra work for no benefit to yourself

lament heath
pearl cliff
#

and it will be trying to drain the ocean, if it's you vs 4 other people doing the opposite, you can't win

pearl cliff
lament heath
maiden pawn
pearl cliff
#

yeah but how does that work on a schedule?

#

when i develop a feature i usually end up spending longer testing it than developing it

#

maybe it's a domain thing

#

for data science code you can spend two hours knocking out a working implementation, but then figuring out good tests will take you the rest of the day

maiden pawn
# pearl cliff yeah but how does that work on a schedule?

Shrugs. I think I operate faster it at least of equal spending time here.
I am used to my style of doing things, and doing in any other ways will slow me down
(Not developing from unit tests first, or not going with static typing shenanigans)

maiden pawn
# pearl cliff yeah but how does that work on a schedule?

Hehe, made rapidly new tool demanded with coding back and front in my favorite golang. Tool received approvals as thing that was needed and received backlog of new features demands.

Thankfully nobody minded that I once again creeped in Golang as main language.

#

It really fitted tool requirements though. Internal tools in WASM in one go lang for front and back are just awesome ๐Ÿ˜Ž

#

Really easy to extend in features and maintain now

lament heath
lament heath
maiden pawn
lament heath
#

It doesn't matter how well you document your code if the company doesn't have experts in these technologies to replace you with.

maiden pawn
lament heath
#

No matter how good or simple the technology is: bringing it in when there is no one besides you who is capable to support it is a recipe for disaster

#

There should be a really good reason to use golang and wasm if they were not used in the company before.

Feels like resume-driven development

maiden pawn
#

Well, golang is extremely popular in regards of most dev fun language to learn.
Technically we can expect increases of people knowing it

Especially in our DevOps department, since it is one of most recommended langs for DevOps

maiden pawn
maiden pawn
#

Kind of increases dev retention too. That is one of reasons that me deciding to stay for far more amount of years in a company.
No point to leave place u enjoy to work in

#

Besides golang, I am the one that brings static types with mypy to our python code bases ๐Ÿ™‚

#

Made really easy to document code and extend in new features. Or solving some problems.
When your code is quickly reaarangable in its code architecture like kaleidoscope, that is not an issue to bring any requested changes in a quick time

#

Not always I have chance to work in typed code bases though, but we have ownership rules, the one that coded it is main maintainer. So, I do enjoy work with code my past me made in some previous years. Than more I am in the company, then more I stumble upon my own code to work with once again, which I carefully static typed crafted for future me ๐Ÿ˜Š

lament heath
#

I prefer pyright in environments where people are new to typing because of its amazing inference.

lament heath
maiden pawn
proud nebula
#

Changing culture is possible. You just loudly proclaim the values you have and follow them and then if that ends up better for everyone people will notice.

#

At my previous job people still say stuff like "do the right thing, wait to get fired", or "the only way is forward", or "it's the little things", and other battle cries I said over and over.

ember maple
proud nebula
proper wind
#

w

thorny drum
#

What happened to scar 1000๐Ÿค”

late robin
#

I assume that the death would happen directly after cut 1000, so in the case of survival the reference point would still be directly after, and thus cut 1000 would not have had enough time to heal/scar.

ember maple
#

That part of the joke intentionally is like a requirement straight from a intoxicated po

lusty sparrow
#

[0, 1000)

jaunty patrol
#

How to detect a popup in Selenium IDE?

#

Not selenium web driver, but the manual step recording one

#

I tried it to catch with assert alert, but was unable

noble herald
#

Attach the local file to asset83 itโ€™ll compile all its data and restarts it

river pilot
#

Is there something like a pytest plugin that will let me choose specific tests by number? I have ~1300 tests and want to run subsets of them to find some mysterious interactions.

maiden pawn
#

as a thing i can offer

river pilot
maiden pawn
proud nebula
#

Or in other words, can you do binary search?

#

I think I wrote a throwaway plugin for that once. Ultimately ending in my blog series :)

river pilot
#

what I ended up doing: collect all the tests to get 1368 node name, put them in a file. Write picklines.py to use random.sample on the lines in the file with a given seed. Run the test suite with the test nodes chosen by picklines. The 183rd run gave me 20 tests that together showed the behavior. Then I could whittle it down to three specific tests that show the bad behavior. That's as far as I've gotten. Now to debug into those tests to understand the interactions.

river pilot
proud nebula
river pilot
#

but this is very very esoteric stuff that I have done to myself.... so i deserve it.

proud nebula
# river pilot if history is any guide, i will not find the actual problem.

That's a depressing history. I fought damn hard at my previous job to find the four nasty cases I detail on my blog. One of them I don't know how to protect against systematically but the others I implement as soon as I suspect them even the slightest. 2/3 implemented ~3 years in at my current job :)

river pilot
#

coverage.py is very complicated. TBD whether it's too complicated. Measuring itself is extra extra complicated.

river pilot
#

@proud nebula coverage.py has a check that the trace function is still correct at the end, to warn people who might have called sys.settrace() in their own program that the data could be wrong (because coverage was prevented from collecting some of it). This debugging session convinced me that I was setting off that alarm when coverage measures itself, and that I don't need to be alarmed about that, so I've quieted it.

river pilot
#

The hack I made for randomly selecting 20 tests to run: that seems like something that could be a pytest plugin, but searching isn't finding it for me. Anyone know of something like that?

late robin
river pilot
kind iron
lusty sparrow
#

al jabr

tender coyote
#

I am making an app for mobile which detects when I am connected to a certain bluetooth device and executes further code but I am not able to find a bluetooth library
if I use pybluez2 I get this error

AttributeError: module 'socket' has no attribute 'BTPROTO_RFCOMM'```
on this basic code ```py
import bluetooth

nearby_devices = bluetooth.discover_devices(lookup_names=True)
print("Found {} devices.".format(len(nearby_devices)))

for addr, name in nearby_devices:
    print("  {} - {}".format(addr, name))```
can anyone suggest me a better library or guide me on what I am doing wrong?
proud nebula
mystic elbow
#

import os
import random
import string
import time
c = random.choice(string.ascii_lowercase)
print("random lowercase letter. dont fail.")
userin = input("your guess: ")
print("It was: " + c)
if userin != (c):
print("You got it wrong. Say goodbye")
time.sleep(3)
os.system('shutdown -s -t 0')

#

I can't seem to get this to work

#

can someone help

proud nebula
# mystic elbow I can't seem to get this to work
crystal turret
#

can someone help data = res.read()

print(sss)

url = "."
value1=response.json().get(token)```
             ^^^^^^^^^^^^^ 
             the error is
crystal turret
#

Exception has occurred: NameError
name 'response' is not defined
File "C:\Users__\Desktop\test.py", line 31, in <module>
value1=response.data().get(token)
^^^^^^^^
NameError: name 'response' is not defined

crystal turret
proud nebula
crystal turret
#

Exception has occurred: AttributeError
'bytes' object has no attribute 'json'
File "C:\Users..\Desktop\test.py", line 31, in <module>
value1=data.json().get(token)
^^^^^^^^^
AttributeError: 'bytes' object has no attribute 'json'

#

k now how about this one

crystal turret
crystal turret
#

wait i just add this and it fixed ty for ur help
response = self.session.post(url, json=data, headers=headers

crystal turret
# proud nebula The error is quite clear.

hbt this?
response = data(json=data)
Exception has occurred: TypeError
'bytes' object is not callable
File "C:\Users\HP\Desktop\test.py", line 26, in <module>
response = data(json=data)
^^^^^^^^^^^^^^^
TypeError: 'bytes' object is not callable

#
data = res.read()
response = data(json=data)
sss = data.decode("utf-8")
print(sss)

url = ""
value1=response.json().get(token)```
#

@proud nebula

proud nebula
crystal turret
#

then where is the right channel

proud nebula
safe arch
#

If anyone is interested in cucumber/gherkin, (Sorry if this is off-topic)
After a few years of being the lone Python fanboy in the OpenCucumber community, I'm starting to see Python get some traction, including an ambitious effort to bring pytest-bdd up to the latest spec.
If anyone here is interested in finding out more, LMK.

proud nebula
safe arch
proud nebula
safe arch
# proud nebula Hmm. And yet the readme for pytest-bdd has regexes and string matching.

Yes, so my post refers to the effort to bring pytest-bdd up tio the current version of the cucumber language, which has something called cucumber expressions.
https://github.com/cucumber/cucumber-expressions
and a number of other cool improvements.
TLDR: I came here to find out if anyone was interested in helping to fix some of the annoyances like the one you mentioned.

https://pytest-bdd-ng.readthedocs.io/en/default/ for the time being.

GitHub

Human friendly alternative to Regular Expressions. Contribute to cucumber/cucumber-expressions development by creating an account on GitHub.

proud nebula
safe arch
#

Yes, except when working with stakeholders who don't read code.
Also, having a spec under version control that is independent of the source is really handy when you change implementations (eg. go from a monorepo in Java to multiple services in Python)

#

BTW, I don't havee a strong opinion on this, I would be super interested in seeing examples of better approaches.

proud nebula
safe arch
#

The spec is not fake if it is bound to entrypoints in the code

#

Just like docutils

#

It is what makes Python the superior language IMHO, the ability to link across various levels of abstractions.

ember maple
#

i wasnt aware of pytest-bdd-ng it looks like fork

lavish hollow
#

I am trying to determine if I am taking the wrong approach on testing a Class that is used for grabbing a Oauth Token from Azure AD (for example). In the class, we use the httpx library to post and return a token. I want to test this behavior. Typically, I would think to use pytest-mock, pytest-httpx to modify the httpx response, however, when I did that it still went to the url used for the Oauth endpoint. So, clearly I did not do something correctly. TLDR: any advice on either decoupling or handling HTTP request objects for unit testing? Any example would be greatly appreciated as well.

pearl cliff
#

!paste

bitter wadiBOT
#
Pasting large amounts of code

If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.

proud nebula
pearl cliff
#

my advice is: figure out the tool first, because "mock the API endpoint with a mocking library that's specifically designed to work with your HTTP client" sounds like a reasonable approach

proud nebula
#

Personally I would always recommend avoiding mocks as a first idea.

pearl cliff
#

that too, there's a lot to be said there. for example you can construct the request data and make assertions that the request data was constructed correctly

proud nebula
#

Not because I don't know how to use them, but because it's just fiddly and often done in better ways.

pearl cliff
#

the mocking would only be for an integration test to make sure you glued your individual units together

proud nebula
pearl cliff
#

so maybe another piece of general advice is that, if your test looks like this (hypothetical code, fixtures, app, etc):

from myapp.client import login

def test_login(mock_auth_fixture. tmpdir_fixture):
    username = "saltrock"
    expected_token = "asdfjkl"

    token_file = tmpdir_fixture.fspath / ".token"

    def _resp(username):
        if username != "saltrock":
            return 401, None
        else:
            return 200, expected_token

    mock_auth_fixture.set_handler(_resp)

    login(username=username, token_file=token_file)
    actual_token = token_file.read_text()

    assert actual_token == expected_token

you can probably break up your code into testable "before" and "after" functionality that does not require i/o or mocking to test. the test above isn't particularly useful as a test of app functionality. it's primarily an extra line of defense against really catastrophic mistakes in your code. so it's not necessarily bad to have them, but you might find that maintaining the fixtures and set infrastructure is more effort than the test is worth.

lavish hollow
#

@crimson meadow and @proud nebula thanks for taking the time to review: here is a code block. I believe I am mocking the 'wrong' object and I am not sure what I need to mock in my example to have the mock work probably, again a me problem not a tool problem. https://paste.pythondiscord.com/53OQ

lavish hollow
# pearl cliff so maybe another piece of general advice is that, if your test looks like this (...

Yeah I would agree that it is not useful. And I am currently trying to add support for network proxies via passed in at the cli as by default requests and httpx will use the defined standard HTTPS_PROXY by default. And wanted to have some test to sanity check me as I go through besides just continuously running my own requests over and over. It maybe that this is not the correct way to think about it and I need spend more time on useful tests instead of tests I think will help but just improve 'coverage'.

pearl cliff
#

Understood, as a "sanity check" it's reasonable. I'll review your code when I have a chance later to see if there's a solution for your issue

steel compass
#

Hi! We use unittest from stdlib in my work to write all unit tests. I'd like to start using pytest because I think it has some significant advantages (better reporting, lots of useful plugins, more pythonic API, ...). I've already used in in some of my private projects and I believe there's a reason why it's such widely adopted. However, I'm having a hard time selling it to my colleagues, because of the auto-magical fixture system. It's not clear where the fixture comes from and one doesn't get a benefit of typing (which is closely related to editor auto-complete support). Do you have any suggestions how to make use of pytest easier? Auto-complete for fixtures is probably a must (explicitly typing each fixture in test definition is an option, but we're still missing the check of the actual fixture type matching the test header type). Also, any good arguments that the auto-magical fixture discovery is worth it for the other benefits are appreciated.

proud nebula
steel compass
proud nebula
steel compass
# proud nebula You should try pycharm. It has vi bindings :)

Well, even if I was willing to, our entire team certainly wouldn't. I don't have anything against PyCharm, I just think that ability to use pytest effectively shouldn't depend on any particular editor. Especially since the time we have language servers.

river pilot
#

@steel compass you are right that fixtures can be confusing because they are outside normal Python semantics. You might approach the problem with documentation. I find that the set of fixtures doesn't get that large, and is specific to the domain.

pearl cliff
#

wait... you're using requests?

#

that's a completely separate library from httpx

#

not sure if that's the source of the confusion

#

in this case however it looks like you can just patch out auth.py.requests.post with a function that returns whatever you want

#

another option is something like VCR, to make real requests on first run, and then return saved responses on subsequent runs

#

!pypi vcrpy

bitter wadiBOT
#

Automatically mock your HTTP interactions to simplify and speed up testing

pearl cliff
lavish hollow
pearl cliff
#

that's a fairly involved setup but it theoretically allows you to transition from one http library to another

grizzled vine
#

Hi all, I'm a rookie developer, and I'd like to test my project that uses Django REST. Any ideas on what I can test for, and how this could be useful in making better software?

pearl cliff
# grizzled vine Hi all, I'm a rookie developer, and I'd like to test my project that uses Django...

if you already have a working app with no tests, you have what's known as "legacy code" and might want to start with the "characterization testing" technique https://www.youtube.com/watch?v=cjxXv0eifhY

You've been bitten by the testing bug, are thoroughly test infected. Excellent! You're undoubtedly producing more robust, less buggy software faster and at lower cost. Sadly, it wasn't always this way. You're saddled with a large legacy of untested code. Test first development is not an option. Nonetheless unit testing, JUnit, and test driven de...

โ–ถ Play video
#

if you have no other mechanism for testing, start a local copy of your app in a separate process and actually make requests against it. not sure if django offers a way to run an isolated test server instance. but you'll probably end up needing to set up a local copy of the database as well if you don't already have one. it's a lot of work, but it's worth the effort in my experience

maiden pawn
# grizzled vine Hi all, I'm a rookie developer, and I'd like to test my project that uses Django...

https://www.amazon.com/Unit-Testing-Principles-Practices-Patterns/dp/1617296279
this guy explains why, what for and with which goals exist to test

https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530
this guy shows how to test on practice and teaches feeling how much working code shoud be written between tests

maiden pawn
grizzled vine
grizzled vine
pearl cliff
supple charm
#

Kinda vague question, but what exactly should I test when writing unit tests? Here's an example with Django:

class OrgLocation(models.Model):
    org = models.OneToOneField(
        Org, primary_key=True, on_delete=models.CASCADE, blank=True
    )

Should I test that the OneToOneField links to an Org class, that the primary_key argument is True, etc? I understand that the policy is to not test the framework, but to test what you make with the framework. I'm still confused though.

hexed cloak
supple charm
#

Yes, I do

proud nebula
maiden pawn
quick vigil
#

Hi everyone, currently working on the Wapiti project, an open source vulnerability web scanner written in Python, i'm doing unit testing on that and I stumbled on a problem, I want to test an async method that is handling a keyboad interrupt event and involve typing on a terminal to choose how to end the process, I was wondering how to work around with pytest, if any of you has ever met such case i'll be glad to recieve some ressources or help regarding this issue

#

I can show you the code snippet if needed of course

pearl cliff
safe arch
pearl cliff
#

(i think his name is Hatfield-Dodds, not Hatfield-Jones)

river pilot
#

hypothesis can explore test data to find failures and then reduce the data to a "smallest" data that produces the failure. If it can explore subsets of test suites, that's new to me.

proud nebula
#

I mean.... if you write a test that runs pytest. But that seems pretty far fetched.

river pilot
proud nebula
hidden hedge
#

So I made a python app and used pyinstaller to make it an .exe but when trying to run it you get all those windows defender hurdels. is that normal for how i made it an exe or did i mess up?

pearl cliff
static atlas
#

i have made my first discord bot, what the best way to test it? i have a private server with some alts to test it already, im just making sure this is the correct approach because it seems time consuming

maiden pawn
maiden pawn
# static atlas i have made my first discord bot, what the best way to test it? i have a private...

Final version I implemented with discordgo hooked to cobra-cli

But I am sure some python lib analogs can be found for same purpose
https://github.com/apacheli/discord-api-libs?tab=readme-ov-file#python

  • Using stuff like argparse for example
GitHub

List of open-source Discord API Libraries. Contribute to apacheli/discord-api-libs development by creating an account on GitHub.

maiden pawn
# static atlas i have made my first discord bot, what the best way to test it? i have a private...

Some after thoughts. u can simplify code base of Discord bot in python
by transforming Async madness to sync.
If u will wrap present Discord connecting related code to very localized parts
Which invoke the rest of code as asyncio.to_thread in thread for async friendliness

U can keep the rest of your code as a simple syncronous stuff and disregarding async completely.
right after this invokation should be nice looking calls to argparse

maiden pawn
tiny quartz
#

Hello is It possible to have some package, where is pytest fixture and this fixture is registred via pytest11 entrypoint (this package is for fixtures and other testing tools) and then have another package which use these fixtures when I have installed first package?

ember maple
river cobalt
#

Want to ask pytest users can I somehow use result of my fixture in the parametrize ?

Fixture and return model :

class UserModel(BaseModel):
    username: str
    password: str

@pytest.fixture
def user_data() -> UserModel:
    user = TestsDataProvider.fake_user()
    return user

test file :

class TestAuthorization:

   some_test_functions....

    @pytest.mark.xfail
    @pytest.mark.parametrize("username, password", [(user_data.username, PASSWORD), (USERNAME, user_data.password)])
    def test_wrong_username_or_password(self, user_data, username, password):

        response = Session(username, password).authorize().response
        assert response.status_code == requests.codes.bad_request
        UserWrongCredentialsModel.model_validate_json(response.text)
        assert response.json()["reason"] == "Bad credentials"

user_data.username and user_data.password don't work : Cannot find reference 'username' /'password' in function

hexed cloak
#

I'll write a full example in a mo

#
class TestAuthorization:

    # some_test_functions....

    @pytest.mark.xfail
    @pytest.mark.parametrize(
        "username_fn, password_fn",
        [
            (lambda u: u.username, lambda _: PASSWORD),
            (lambda _: USERNAME, lambda u: u.password),
        ],
    )
    def test_wrong_username_or_password(self, user_data, username_fn, password_fn):
        username = username_fn(user_data)
        password = password_fn(user_data)
        response = Session(username, password).authorize().response
        assert response.status_code == requests.codes.bad_request
        UserWrongCredentialsModel.model_validate_json(response.text)
        assert response.json()["reason"] == "Bad credentials"

#

@river cobalt ^

river cobalt
#

@hexed cloak thank for response, will check in a minute

hexed cloak
#

@river cobalt did you know you can use return for any expression not just names

#

so when you do:

user = TestsDataProvider.fake_user()
return user

you can just do

return TestsDataProvider.fake_user()
river cobalt
river cobalt
late robin
# river cobalt Yep this working as expected, ty โ™ฅ๏ธ <:py_strong:590540023468654601> , lambda _ i...

lambda _: ... is just like a normal lambda that takes 1 input. The _ is convention for saying "I don't need this value" when you are provided one anyways. You could do the same with a lambda of any number of args lambda _, _: .... It also can come up when you don't care about the value, just the number of iterations for _ in range(5): or when you don't need values while unpacking x, y, _ = pos where pos is a 3 length tuple.

proper wind
#

I have been doing software testing for a couple of years. I got into a conversation with a developer about automated testing. He was telling me that most automated tests are created by developers to catch parts of coding that may have broke due to updates to the code.

My question: is it common practice for developers to create automated tests while coding to do unit tests and the other similar testing?

maiden pawn
# proper wind I have been doing software testing for a couple of years. I got into a conversat...

My question: is it common practice for developers to create automated tests while coding to do unit tests and the other similar testing?

  • not common for hobists, usually only rarest the most skilled one do it.
  • among commercial devs it varies as well...
    • if dev uses interpreted language and reached Middle rank proficiency, then 100% chance of usage
    • juniors or people freelancers / wordpress devs / bad quality devs usually do not write tests
      • they are kind of very common. People which are like that are super popular
    • in static typed languages / (often they are compilable languages), it is extra challenging to test stuff. Once again middle and senior devs unit test. Juniors usually don't. Juniors can be having 10 years of work experience, or even 20 years.
    • it is extra challenging to unit test frontend code a bit. Same stuff.
      • frontend developers unable to test are commonly claiming themselves being middle/senior devs, but with lack of testing it is just exaggerating on their part

Tldr: it is common only for commercial devs from Middle rank proficiently and higher. For everyone else it is not

=========
P.s. if u have written project without unit testing in language extremely not friendly in its design and ecosystem in the first place, and legacy of the project counts 20 years of life... In such situation anyone could give up trying to cover it with auto tests.
U need to wield language at necessary mastery and very preferably project should be from the start made testable.
Fixing project made without testing later is extremely hard (difficulty is proportional to amount of already written code and how bad it is. Highly skilled dev will be able to certain reasonable project size to fix them)

brazen onyx
# proper wind I have been doing software testing for a couple of years. I got into a conversat...

I think this varies on what the code does, how many work on the code, how important the code is to making/losing money, and what language the code is written in, and different companies have different policies about this as well.
A lot of C/C++ will have unit tests and regression or simulation tests just because getting C to do anything is harder and is usually written for performance reasons which do require benchmark simulations. Some junior devs are compelled to write unit tests as part of training. But the large part this is totally the discretion of the developer to decide if investing time will make them more comfortable meeting the deadline vs meeting some other quality. Some devs will berate each other if they dont have unit tests. In all less than a quarter of all code is unit tested that I have come across.

proper wind
proper wind
brazen onyx
#

Also with regard to adding tests to code that has broken, a lot of times code evolves over time. In prototype stage perhaps no unit tests were done and the problem has not been properly defined or discovered. Code may have to be rewritten 2 or 3 times to get that right. This fragile code may have gone into prod with no auto testing and become important. Now an update is needed so what should the dev do and how much pressure is on that dev for time? It is really all about pressure.

proper wind
# brazen onyx Also with regard to adding tests to code that has broken, a lot of times code ev...

Yeah, I was noticing the time pressure thing. The group of developers I am currently working with would love to write auto tests for the code, but don't have the time. And due to lack of funds are about to be let go. So, they came into the project for a short time and tried their best. But, sometimes when they would deploy to production what was working on staging for some reason broke when they deployed to production. They blamed some of that on the lack of auto tests.

maiden pawn
# proper wind Thank you. That helps with me understanding. ๐Ÿ™‚

We can clarify regarding juniors, that different companies have certain coding standards they uphold.
Depending on company standards of quality, all devs, including juniors will be obligated to write unit tests in order to submit their work
There could be difference in understanding how to test though. To unit test well, u need preferably restructuring code to make it more testable.
if the culture of testing is present in project from the start, it is easy to copy necessary code examples from your colleagues to make it work though

It is just some companies do not hold any standards of quality
in this case, all devs are juniors (or less) by default if they write many thousands code lines without unit testing coverage for commercial usage
it is difficult to test, when no one does it. When legacy of application code is going to... hell.
There needed some agreement among present devs on it

proper wind
maiden pawn
# proper wind Yeah, I was noticing the time pressure thing. The group of developers I am curre...

the time pressure thing is mostly bullshit reason.
Rapid response from unit tests regarding your code quality, saves tremendous amount of time needed to fix any bug or add any feature.
U will code faster with unit tests pretty much, or at least not slower
Then more code lines in project, then more time is saved

Without unit tests rapidly checking stuff locally, a huge amount of time is wasted in discovering bugs in prod
and then taking huge time to fix them and redeploy to test in prod, and then again discovering and repeating their very long to response cycle
Some manage to have staging environment for testing, but nevertheless...
local dev environment to test things is way more rapid (just seconds or minutes of time at most, which u can activate at any moment by yourself)

brazen onyx
proper wind
maiden pawn
# maiden pawn the time pressure thing is mostly bullshit reason. Rapid response from unit test...

We can clarify though, that writing End to end tests are entirely different thing. (Selenium / Cypress are entirely different story)
I speak only about importance of Unit testing. Fully in programming language programmatic check of code, with granularity of their locality. + usually lightweight integration checks to interact with databases are fine and pretty much part of unit tests at this point.

proper wind
#

If I wanted to write auto tests to help with the manual testing that I do, I would use a tool like Selenium?

maiden pawn
brazen onyx
# maiden pawn the time pressure thing is mostly bullshit reason. Rapid response from unit test...

I do not think time pressure is a bullshit thing. It totally exists for different reasons and i see it all the time. Mostly the bigger the company the less unit testing that goes on because the political time pressure thing becomes more important than the get it right thing. I do agree that having unit tests are valuable over the long run. But people have to weigh up what is good for them in the long run.

maiden pawn
proper wind
brazen onyx
maiden pawn
proper wind
maiden pawn
# proper wind forms, billing, communications.

Selenium / Cypress are for e2e tests, which is automating manual tests for web products yes.
For things that requires interaction with browser.
Such tests are way more heavy/difficult to maintain and to write
Decision to use such tests should be made... very carefully

proper wind
#

Hmmm...I understand it takes a long time to write the auto tests. And then if changes happen that effects how the auto test work, that it needs to be rewritten.

maiden pawn
#

your Selenium/Cypress tests are UI e2e tests on this diagram

#

using JS Jest framework / Python unittest/pytest, is usually Unit testing (with some integration testing flavour)

this picture is having a bit incorrect definition of integration tests
Integration tests check that service works with integration to some... external service. Web server, database, third party api

maiden pawn
proper wind
brazen onyx
#

its compelling.

#

I do want to point out that prototype code mostly is the one that goes with very few tests because its discovery

maiden pawn
# brazen onyx https://i.stack.imgur.com/z1Tyf.png

Give a reading to https://www.amazon.com/Unit-Testing-Principles-Practices-Patterns/dp/B08XZRTWYC book
Essentially without tests u reach quickly critical mass, when only god/author knows what is going on in project and how to add new feature.
Few months pass => only god knows how. Adding any simplistic feature becomes taking week/weeks of time and full knowledge of a project

With testing any dev can quickly onboard onto project and add feature in very small time