#unit-testing

1 messages Β· Page 9 of 1

pearl cliff
#

you might have 5 test methods but only want that fixture in 3 of them

hexed meadow
#

I'm talking about having an __init__ function

#

if you have an init, all the test methods require an instance of the object anyway

#

so init has to be called

pearl cliff
#

oh. again, i think that was done to avoid compatibility issues with existing established uses of __init__ in test classes

#

it's not that you can't do those things in a fixture, it's that people were doing them in __init__. you'd have to dig around for the actual explanation.

hexed meadow
#

right. I guess that was likely reasonable at the time but it ends up making this feel pretty unnatural

pearl cliff
#

i agree that it would be convenient if __init__ was treated like an always-available autouse fixture

hexed meadow
#

To be quite honest if I was writing these tests from scratch I would do the thing I mentioned above

pearl cliff
#

this thing?

hexed meadow
#

yeah

pearl cliff
#

yeah, that's idiomatic

#

(not the only idiom, but it's a very common strategy)

hexed meadow
#

Okay, good to know I'm not far off

#

The advantage there is that it separates which tests are using the fixture, from other things you might want to achieve by organizing the tests into a class

#

like, for example, we often use skip_if at class level

pearl cliff
#

right. you can apply other marks at the class level too if you want (e.g. to mark a class as a regression test, as per our discussion the other day)

hexed meadow
#

if you organize it this way, you can for example put a skip_if on all 10 of your tests at once, but only 5 of them actually need the fixture

#

the funny thing is that in the end the failing test case wasn't where I thought so I'm just leaving this file alone πŸ˜‚

#

thsi file just had a warning

#

but now I'll probably use that modify collection hook.
I have this regression path thing, which some tests are now going to accept as a fixture, and they'll be auto skipped if the regression path is not passed.
but some tests don't actually need the regression path itself, but I still want to only run them in "regression mode"

#

This could be achieved by having them still take the reg_path fixture, but it would be unused. So I'm thinking that a decorator is a better approach?

pearl cliff
#

i still encourage using a mark to indicate which tests are regression tests

#

but yes, i think it makes sense to expose a regression_path fixture

hexed meadow
#

I already have a regression_path fixture

#

I'm not sure why I'd need both a mark and accepting the fixture; that seems redundant?

#

This is for cases where the fixture isn't actually needed, but I still want to only run it in regression mode

#

@pytest.mark.regress would work I guess

#

and then modify in collections

#

one thing I really dont' like here is that if you make a typo, then it just silently works incorrectly

#

whereas, if you write a test that asks for a non-existent fixture it will fail

proud nebula
#

imo it should be the default, but I guess there would be massive backwards compatibility breakage if they did that

pearl cliff
pearl cliff
hexed meadow
#
def some_test(reg_path: Path):
    ...

it's already clear that this is a regression test

#

I mean I considered just doing it that way even if reg_path is unused but I figured that people would be unhappy that their linters complain and so on

hexed meadow
#

Feel much better about using that now

proud nebula
pearl cliff
#

i think that was in one of the SO posts i shared the other day

hexed meadow
#

is there a way to make pytest_collection_modifyitems query another fixture?

proud nebula
hexed meadow
#
def pytest_collection_modifyitems(config, items):
    if config.getoption("--runslow"):
        # --runslow given in cli: do not skip slow tests
        return
    skip_slow = pytest.mark.skip(reason="need --runslow option to run")
    for item in items:
        if "slow" in item.keywords:
            item.add_marker(skip_slow)
#

that's fine for me; but the catch is that what I depend on is not a "simple" command line option

#

rather, I have a fixture that figures out the regression path, based on two command line options, and some logic

#
@pytest.fixture(scope="session")
def reg_path(request) -> Path:
    explicit_reg_str = request.config.getoption("--regression-path")
    reg_env_bool = request.config.getoption("--regress")
    ... logic
pearl cliff
hexed meadow
#

No, that's not what I want

#

in an ideal world, I would have

def pytest_collection_modifyitems(config, items, reg_path)
#

or something like that

#

I want pytest_collection_modifyitems to get the value of the fixture

#

it seems like you can do this from the request argument

pearl cliff
#
def pytest_collection_modifyitems(config, items):
    reg_path_value = config.getoption("--regression-path")
    ...

like that?

hexed meadow
#

request.getfixturevalue('load_data')

#

that's not the value of the fixture?

#

that's just th ecommand line argument

pearl cliff
#

oh. i see.

#

wait, why do you want that?

#

i don't think that's possible from modifyitems. the fixture hasn't actually been run at that point afaik.

hexed meadow
#

because, there's two different optiosn that can cause me to run in "regression mode" ?

pearl cliff
#

yeah but why are you checking the fixture value here?

hexed meadow
#

I want to filter out any tests marked as "regress", if I'm not running in regression mode

#

the logic that figures out whether I'm in regression mode, is effectively already there in the reg_path fixture

#

the best thing would be to ask for that fixture's value

pearl cliff
#

i'm still not understanding why you need modifyitems here

#

i think you do need to separate the --regress and --regression-path logic though

hexed meadow
#

to potentially skip any tests marked as @pytest.mark.regress

#

I mean yeah, the way thigns are headed I'm going to have to factor it out into a separate function, that gets called twice

#

pretty lame

#
@pytest.fixture(scope="session")
def reg_path(config) -> Path:
    ...

since my reg_path fixture only uses the config field of request, I think I can just refactor it like this
and then have pytest_collection_modifyitems(config, items) call reg_path(config)

#

it's not really a big deal but just kind of silly that the logic is running twice

#

do you see a better way to do it?

#

I see a lot of comments online about people not understanding why hooks cannot simply take fixtures directly the same way tests can

pearl cliff
#

i think so... hang on

pearl cliff
#

build graph first, then run it

hexed meadow
#

fixtures run as-needed

pearl cliff
#

yes, but not during collection

#

collection is a distinct phase before execution

hexed meadow
#

I mean, you're describing how it currently works, yes πŸ™‚

pearl cliff
#

but that's the answer why

#

you'd be asking pytest to fundamentally change its design and execution model, in order to do something that you probably shouldn't do anyway

hexed meadow
#

why should I probably not do this?

#

this is a... very simple use case

pearl cliff
#

because it's a good design to keep collection and execution separate πŸ˜›

#

it would be so much harder to reason about otherwise. not to mention much harder to debug

hexed meadow
#

I mean the issue is that arguably, it's a hack for reg_path to be a "fixture" to start with

#

it's not a fixture in the proper sense

#

it should be part of the config

pearl cliff
#

it is part of the config. it's just that you can't access the config from inside a test (afaik)

#

so maybe that might be an unnecessary limitation

hexed meadow
#

okay, then obviously there is something flawed in the design here?

#

I don't think there's anything unusual about my use case, basically

pearl cliff
#
from collections.abc import Sequence
from pathlib import Path

import pytest

def pytest_collection_modifyitems(config: pytest.Config, items: Sequence[pytest.Item]) -> None:

    # All tests using the "reg_path" fixture should also be marked with "regress".
    mark_regress = pytest.mark.regress()
    for item in items:
        if "reg_path" in test_item.fixturenames:
            item.add_marker(mark_regress)

    # Tests marked with "regress" should not run unless the --regress option is used.
    skip_regress = not config.getoption("--regress", default=False)
    if skip_regress:
        mark_skip_regress = pytest.mark.skip(reason="Use --regress option to run regression tests.")
        for item in items:
            if "regress" in item.keywords:
                item.add_marker(mark_skip_regress)


@pytest.fixture
def reg_path(config: pytest.Config) -> Path:
    return Path(config.getoption("--regress-path", default=False))

what about something like that?

hexed meadow
#

this is fundamentally different to before

pearl cliff
#

this is how i'd attempt to implement what i understood your goal to be

hexed meadow
#

if --regress is specified then reg_path will attempt to get the path from an environment variable

pearl cliff
#

oh right, i missed that detail

hexed meadow
#

but I mean, it seems like the import bit is just changing reg_path to take a config

#

and then calling reg_path from pytest_collection_modifyitems

pearl cliff
#
import os
from collections.abc import Sequence
from pathlib import Path

import pytest


def pytest_collection_modifyitems(config: pytest.Config, items: Sequence[pytest.Item]) -> None:

    # All tests using the "reg_path" fixture should also be marked with "regress".
    mark_regress = pytest.mark.regress()
    for item in items:
        if "reg_path" in test_item.fixturenames:
            item.add_marker(mark_regress)

    # Tests marked with "regress" should not run unless the --regress option is used.
    skip_regress = not config.getoption("--regress", default=False)
    if skip_regress:
        mark_skip_regress = pytest.mark.skip(reason="Use --regress option to run regression tests.")
        for item in items:
            if "regress" in item.keywords:
                item.add_marker(mark_skip_regress)


@pytest.fixture
def reg_path(request: pytest.FixtureRequest) -> Path:
    config = request.config
    path_cmd = config.getoption("--regress-path", default=None)
    path_env = os.environ.get("TEST_REGRESS_PATH", None)
    path_setting = path_cmd or path_env
    if path_setting is None:
         pytest.skip("TEST_REGRESS_PATH and --regress-path are unset, cannot run.")
    else:
        return Path(path_setting)
#

and wait, i might need request.config

#

let me check the docs

#

this is of course untested and off-the-cuff

#

yep, hang on

hexed meadow
#

this is still not correct...

pearl cliff
#

edited

hexed meadow
#

if --regress-path is specified then tests marked regress should still be run

pearl cliff
#

okay then. you get the point though, right?

hexed meadow
#

I mean, yeah, I get that I have the option to just duplicate the logic

pearl cliff
#

just change skip_regress in the modifyitems hook to check for the presence of either options

hexed meadow
#

why is that better than calling reg_path from pytest_collection_modifyitems?

pearl cliff
#

(fwiw i don't think this is actually a very common use case)

#

the reason is that it's not possible, and the data/executino model is what it is.

hexed meadow
#

def pytest_collection_modifyitems(config, items):
    try:
        reg_path(config)
        return # if no exception, then that means we have a regression path
    except:
        pass
#

huh?

#

what's not possible?

pearl cliff
#

manually calling the fixture function? anything is possible. but the arg needs to be a FixtureRequest not a Config, i made a mistake in my code above

#

you could of course have a common function for that

hexed meadow
#

ah, I thought you could just have it take a config and it would work

#

yeah, then I have to factor out into a common function

#

pretty lame

pearl cliff
#

i actually think a common function might be worse, just from a software design perspective. because now you're running that skip check in 2 different places.

#

well hang on, let me see

hexed meadow
#

I don't follow that part

pearl cliff
#
import os
from collections.abc import Sequence
from pathlib import Path

import pytest


def _get_reg_path(config: pytest.Config) -> Path | None:
    path_cmd = config.getoption("--regress-path", default=None)
    path_env = os.environ.get("TEST_REGRESS_PATH", None)
    return path_cmd or path_env


def pytest_collection_modifyitems(config: pytest.Config, items: Sequence[pytest.Item]) -> None:

    # All tests using the "reg_path" fixture should also be marked with "regress".
    mark_regress = pytest.mark.regress()
    for item in items:
        if "reg_path" in test_item.fixturenames:
            item.add_marker(mark_regress)

    # Tests marked with "regress" should not run unless the --regress option is used.
    skip_regress = not (
        config.getoption("--regress", default=False) or _get_reg_path(config)
    )
    if skip_regress:
        mark_skip_regress = pytest.mark.skip(reason="Use --regress option to run regression tests.")
        for item in items:
            if "regress" in item.keywords:
                item.add_marker(mark_skip_regress)

@pytest.fixture
def reg_path(request: pytest.FixtureRequest) -> Path:
    path_setting = _get_reg_path(request.config)
    if path_setting is None:
         pytest.skip("TEST_REGRESS_PATH and --regress-path are unset, cannot run.")
    else:
        return Path(path_setting)

maybe like that?

hexed meadow
#

I guess I cannot vouch for how common this is in raw numbers. but it seems like a very vanilla use case? Making the value of a command line argument available to unit tests

pearl cliff
#

i don't think a lot of people use custom CLI options other than plugin authors

#

in part because it's kind of clunky...

hexed meadow
#

Yeah, I mean pytest makes some things here a lot more painful than they need to be

#

the fact that I even need to write custom logic for this extremely simple case is silly; almost any command line argument parser would let this be specified declaratively

pearl cliff
#

after working through this with you, i'll grant that the CLI arg parser is somewhere between "underdeveloped" and "shitty"

hexed meadow
#

fair enough

#

I appreciate the validation πŸ˜›

#

anyhow the final solution won't be so bad

pearl cliff
#

I trust you to wrestle this test suite into submission

hexed meadow
#

yeah, you gotta do what you gotta do

#

Half the reason I'm pushing this stuff in is so that each time my the test suit fails because my coworker has pushed a unit test that expects a random file to be present

#

or a random computer to be accessible

#

I'll just slap reg_path or @pytest.mark.regress` on it

#

hopefully he actually puts the files in our regression repo and rewrites the test to access the file from there

wet chasm
#

I've a question.

As a developer, is it recommended to write unit test for all python codes? Or just for APIs?

sleek orchid
wet chasm
#

I'm beginner so not confident

#

For unit testing which library should I use

proud nebula
proud nebula
#

oh, and beware false prophets who give simple answers

#

I guess that follows from my previous statement, but still

hexed meadow
#

what's the equivalent to unittest.mock.patch in pytest?

maiden pawn
hexed meadow
#

heh. thats valid I suppose. I was thinking if I'm doing this anyway I may as well get rid of all the unittest stuff, but no harm letting this stay I suppose

#

though while googling I've already seen questions about somewhat tricky interactions between patch and fixtures

#

a lot of magic works fine when it's the only magic but when you have two magical things acting on the same function it can get hairy πŸ˜›

#

that's why I suppose I was hoping for a pytest solution

maiden pawn
hexed meadow
#

the code in question actually just uses it as a decorator

#
@patch("foo.bar.func_name")
def test_whatever(func_name):
maiden pawn
hexed meadow
#

indeed

drifting sorrel
#

The closest equivalent in pytest would probably be monkeypatch?

#
def fake_func(*args, **kwargs):
    return "hello world"

def test_something(monkeypatch):
    monkeypatch.setattr(my_namespace.my_module, "my_function", fake_func)
hexed meadow
#

yeah, but this doesn't work well

#

the patch in unittest lets you do things like assert how many times the function was called and with which arguments

pearl cliff
bitter wadiBOT
#

Thin-wrapper around the mock package for easier use with pytest

Released on <t:1697732757:D>.

hexed meadow
#

yeah, I came across that, didn't totally grok the example I think

pearl cliff
hexed meadow
#

I guess what I want is the stub

#

it's just a shame that it's so verbose

#

well, maybe "so" is an exaggeration

#

but more verbose

pearl cliff
#
from pytest_mock import MockerFixture

def test_foo(mocker: MockerFixture) -> None
    mock_foo = mocker.patch("a.b.foo")
    ...
hexed meadow
#

yeah

#

not too bad I guess

#

it would actually be stub

#

actually maybe not

pearl cliff
#

it has the same interface as unittest.mock.patch so you can define any test double that you want

hexed meadow
#

can I use it as a decorator?

pearl cliff
#

yeah that should work, but then of course you don't get access to the thing you patch in

#

or you could use it the context manager

#

pytest-mock doesn't add new functionality, it just reduces some boilerplate

hexed meadow
#

you do get access though

#
@patch("foo.bar.func_name")
def test_whatever(func_name):
pearl cliff
#

oh, yeah

hexed meadow
#

func_name is the patched thing, so you can assert how many times it's been called and such

pearl cliff
#

that should work

hexed meadow
#

I think this is already super concise

#

this is just using unittest.mock

pearl cliff
#

..i forgot it worked that way

hexed meadow
#

the catch is that if you are using this, and using pytest fixtures you have to be extremely careful about parameter order

pearl cliff
#

there might be issues related to interaction with other fixtures

hexed meadow
#

not necessarily wildly intuitive

pearl cliff
#

right, that too

hexed meadow
#

I've been fixing up more stuff, I found a test suite that had a warning because a coworker implemented file cleanup using __del__ πŸ˜›

pearl cliff
#

yikes

hexed meadow
#

probably what happened was, the object was instantiated 3 times for 3 tests, the file was created 3 times in the same place

#

then all the dels run at the end

#

and threw

pearl cliff
#

switch the tests to run on pypy in CI

#

that would shake things up

hexed meadow
#

heh

#

at any rate, I used my first "yield fixture"

#

quite nice

#

I wonder if there's a script that transforms all the different flavors of self.assertEqual etc into simple asserts

#

that's the most time consuming and least interesting part of this

hexed meadow
#

Thanks! Really appreciate that

#

Even if it's not perfect it can save a lot of time

river pilot
proud belfry
#

@proud belfry

inner field
#

Guys, I have strange behaviour I never noticed before..

I have IneEnum class, lets say:

class Numbers(IntEnum):
    one = 1
    two= 2

When I do:

print(f"{Numbers(1)}")

I get: Numbers.one.

BUT once I do it in unittest:

import unittest

class TestNumbers(unittest.TestCase):
    def test_one(self):
        print(f"{Numbers(1)}")
        self.assertTrue(isinstance(Numbers(1), Numbers))

I get: 1

What the hell is going on here? I have not noticed it before. (In pytest).
Python version: 3.10

maiden pawn
maiden pawn
#

are you writing with chatGPT or smth πŸ˜…

inner field
#

On mobile. I obviously cannot post here my real code. This was just a example and I did mistake writting it.

Anyway, if it was what you say, it would return "Numbers(1)" not "1".

maiden pawn
proud nebula
river pilot
maiden pawn
#

yeah... tiny factors like " quotation marks, or ' single quotation marks
or { brackets
everything matters. we can't really help you if u don't write your real code.
We are just debugging wrong issues then

proud nebula
#

print(f'{Numbers(1)!r}') produces very different results and that's pretty subtle

inner field
river pilot
inner field
proud nebula
# inner field I have edited my original post. Now its executable.
from enum import IntEnum


class Numbers(IntEnum):
    one = 1
    two = 2



print(f"{Numbers(1)} first")


import unittest

class TestNumbers(unittest.TestCase):
    def test_one(self):
        print(f"{Numbers(1)} second")
        self.assertTrue(isinstance(Numbers(1), Numbers))


if __name__ == '__main__':
    unittest.main()

prints:

1 first
1 second
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
#

So yea, I still think it's something else going on that you missed and we can't see it because you didn't copy paste the original real code.

river pilot
maiden pawn
gentle swan
#

when using tox and pytest, i get a import error

ImportError while importing test module 'lib/tests/..../test_batched.py'.
Hint: make sure your test modules/packages have valid Python names.
E   ModuleNotFoundError: No module named 'lib/module'

Running pytest on the current venv, works fine

#

python3 -c "from lib import module.py" also works

#

i added to tox.ini

pip3 install -e .

on commands and it worked but now i face with a smaller but new issue

#

nvm\

#

found the issue

#

i had a .coverage file and deleted it

#
flake8: OK βœ” in 24.92 seconds
py311: OK βœ” in 33.05 seconds
py310: OK βœ” in 33.73 seconds
py312: OK βœ” in 34.78 seconds
py39: OK βœ” in 36.08 seconds
  py312: OK (34.78=setup[25.73]+cmd[7.31,1.74] seconds)
  py311: OK (33.05=setup[22.86]+cmd[8.05,2.13] seconds)
  py310: OK (33.73=setup[24.51]+cmd[7.25,1.97] seconds)
  py39: OK (36.08=setup[27.07]+cmd[7.32,1.70] seconds)
  flake8: OK (24.92=setup[22.65]+cmd[2.27] seconds)
  mypy: OK (46.46=setup[26.26]+cmd[20.20] seconds)
  congratulations :) (46.60 seconds)

very good!

bitter wadiBOT
#

:incoming_envelope: :ok_hand: applied timeout to @proper wind until <t:1710733929:f> (10 minutes) (reason: duplicates spam - sent 4 duplicate messages).

The <@&831776746206265384> have been alerted for review.

proud nebula
gentle swan
#

but yeh exactly like that i did

#

no worries tho

#

the problem is solved

#

needed to add a pip3 install -e . before executing pytest

modern hedge
#

tox should be a dev dependency too

gentle swan
proud nebula
#

I guess he uses a src directory structure?

gentle swan
#

yup

modern hedge
#

what's that got to do with dev dependencies?

proud nebula
gentle swan
modern hedge
#

yeah i noticed that pip install -e . is installing tox or pytest (which is why your commands afterwards work)

#

Which means its added as a prod dependency

proud nebula
#

hmm.. no I think you're still confused

gentle swan
# modern hedge yeah i noticed that pip install -e . is installing tox or pytest (which is why y...

????

Obtaining file:Users/.../Lib%20Lib/lib
  Installing build dependencies ... done
  Checking if build backend supports build_editable ... done
  Getting requirements to build editable ... done
  Preparing editable metadata (pyproject.toml) ... done
Building wheels for collected packages: lib
  Building editable for lib (pyproject.toml) ... done
  Created wheel for lib: filename=lib-0.0.0-0.editable-py3-none-any.whl size=1487 sha256=####
Successfully built lib
Installing collected packages: lib
  Attempting uninstall: lib
    Found existing installation: lib 0.0.0
    Uninstalling lib-0.0.0:
      Successfully uninstalled lib-0.0.0
Successfully installed lib-0.0.0
modern hedge
#

@gentle swan can you share your pyproject.toml or setup.cfg?

#

Whatever you are using to store package metadata

gentle swan
#

i got both

proud nebula
modern hedge
#

it installs only prod deps afaik

modern hedge
gentle swan
#
[build-system]
requires = ["setuptools>=69.1.1", "wheel"]
build-backend = "setuptools.build_meta"

[tool.pytest.ini_options]
addopts = "--cov=lib"
testpaths = [
    "tests",
]

[tool.mypy]
mypy_path = "src"
check_untyped_defs = true
disallow_any_generics = true
ignore_missing_imports = true
no_implicit_optional = true
show_error_codes = true
strict_equality = true
warn_redundant_casts = true
warn_return_any = true
warn_unreachable = true
warn_unused_configs = true
no_implicit_reexport = true
#

and cfg

[metadata]
name = lib
description = ...
author = McBrincie212
license = "GNU General Public License v3.0"
license_file = LICENSE
platforms = unix, linux, osx, cygwin, win32
classifiers =
    Programming Language :: Python :: 3
    Programming Language :: Python :: 3 :: Only
    Programming Language :: Python :: 3.12
    Programming Language :: Python :: 3.11
    Programming Language :: Python :: 3.10
    Programming Language :: Python :: 3.9
    Programming Language :: Python :: 3.8
    Programming Language :: Python :: 3.7

[options]
packages = lib
# install_requires = numpy>=1.26.4
python_requires = >= 3.7
package_dir = =src
zip_safe = no

[options.extras_require]
testing =
    pytest>=8.1.1
    pytest-cov>=4.1.0
    mypy>=1.9.0
    flake8>=7.0.0
    tox>=4.14.1


[options.package_data]
lib = py.typed

[flake8]
max-line-length = 200
modern hedge
#

hmm

#

I m wrong nvm

gentle swan
proud nebula
#

yea :P

modern hedge
#

sorry for causing the confusion

gentle swan
#

no probs

modern hedge
#

i just got a bit too habituated with npm recently

proud nebula
#

I am also confused about this stuff constantly :P

gentle swan
#

just know for pip3 install -e .
-e: Editable Mode
. refers to the folder(in my case src)

modern hedge
#

btw you can put all this in pyproject.toml

#

the contents of setup.cfg

gentle swan
proud nebula
#

hopefully uv will fix all this chaos

modern hedge
#

so you have one less file πŸ™‚

gentle swan
#

i was following a tutorial

#

on how to setup automated testing

#

with pytest and tox

modern hedge
gentle swan
#

Take your Python project to the next level of professionalism.

Automated testing in Python is an important way to take your Python project to the next level of dependability and professionalism. There are a lot of steps, but it's not too difficult to setup your tests to run automatically across multiple different operating systems and versions ...

β–Ά Play video
proud nebula
modern hedge
#

i m saying you can put all your setup.cfg contents inside the pyproject.toml itself so you have one less file @gentle swan

#

currently its not wrong, but pyproject.toml was created with the intention of being able to store project metadata

gentle swan
#

like pyproject.toml to setup.cfg

modern hedge
#

possible but idk, pyproject is the modern alternative

#

it depends on whether the tools you use still support setup.cfg configuration

modern hedge
gentle swan
#

we already got pypi

#

so what gives?

proud nebula
modern hedge
#

setuptools is good enough tbh

proud nebula
modern hedge
#

it can handle the most complex packaging requirements already

proud nebula
#

uv is WAY faster

gentle swan
proud nebula
#

So much faster that it could run dependency check before every run command and you wouldn't notice. it would be great.

#

I tried to build some tooling that did the right thing for python once but I couldn't get it to work because pip was too slow. With uv there is hope again

modern hedge
#

get amazed by the power of rust

#

so uv replaces pip or setuptools or both?

gentle swan
proud nebula
#

both afaik. And venv

modern hedge
#

So its more like cargo

proud nebula
#

Ruff has been a huge success so far, so I think they can get people behind this.

proud nebula
modern hedge
#

sounds promising

proud nebula
#

oh yea, and ruff now has a code formatter that is like black but way way faster

#

These guys are doing great work

modern hedge
#

yea i had heard about it when it was in works

gentle swan
#

damn

modern hedge
#

Is it 100% black compatible?

proud nebula
fair cave
#

they have a section for that in the doc

#

its like 99.999%

#

πŸ˜„

hexed meadow
#

I didn't realize ruff was doing packages as well

#

oh sorry, that's a separate thing

#

at any rate, I think conda/mamba are sort of in a separate league from anything else, because they also handle native dependencies. it's a huge gamechanger.

#

it's a shame that often people outside the quantitative python community seem less aware of them

modern hedge
hexed meadow
#

idk, pip is a bit better now but it was like completely broken until relatively recently

#

didn't properly solve dependencies

#

from firsthand experience I think a lot of people just used pip because it was there and then suffered for it

#

rather than it actually being "good enough" in a meaningful way

modern hedge
#

pip is on homeopathy, it gets fixed very slow

quartz meadow
#

Where did you guys read Test Driven Development by Example by Kent Beck?

Kindle version is a bit cursed...

boreal lake
#

Hello, i have a python program which writes something to a file, If i want to create a test for this, whats the best method to do so? When i searched for this i came across unittest.mock. Is that a good method or is there something else which is better than mock

maiden pawn
#

U make only worse with testing less

proud nebula
boreal lake
#

Thanks for the advice, i will look into both

minor crag
#

anybody used pynguin?

hexed meadow
#

question about pytest; when it parallelizes, will it run tests that use the same fixture on different cores?

#

I'm wondering about a fixture that creates and then deletes a file at a fixed location, and whether that would thus be unsafe to parallelize

#

and instead I should use some kind of unique temporary dir instead

maiden pawn
hexed meadow
#

yeah, I'll probably do that, but I just wanted to understand what rules pytest uses for parallelizing, especially different scopes of fixtures

hexed meadow
#

though it does not really seem to discuss fixtures

#

but it seems to me like it just doesn't care about fixtures. it just divies up the tests however it wants and then does the fixtures however

maiden pawn
# hexed meadow but it seems to me like it just doesn't care about fixtures. it just divies up t...

Question: Why does each worker do its own collection, as opposed to having the controller collect once and distribute from that collection to the workers?

If collection was performed by controller then it would have to serialize collected items to send them through the wire, as workers live in another process. The problem is that test items are not easily (impossible?) to serialize, as they contain references to the test functions, fixture managers, config objects, etc. Even if one manages to serialize it, it seems it would be very hard to get it right and easy to break by any small change in pytest.

#

parallelism through Processes does not share memory

hexed meadow
#

well, yes, if you ctrl-f fixture, that is what you find πŸ™‚

#

that doesn't really answer my question in the sense that it could decide to keep tests sharing a fixture that's higher scope than function level, on the same worker

#

for function level fixtures it doesn't technically either, but I guess it's pretty safe to assume that function level fixtures could end up running on different workers unless I see evidence otherwise

#

since in principle it doesn't even save work

maiden pawn
#

u need applying session scope to reuse them

#

but since xdist are Processes, they don't share memory

#

so they rerun everything including migrations on test session start

hexed meadow
#

uhm, again, this doesn't answer my question, but it's okay, if you don't know the answer you don't need to try to answer it πŸ™‚

#

anyhow seems like this answers it at least for session-scoped, not sure about smaller scopes

river pilot
hexed meadow
river pilot
hexed meadow
#

fair enough; it's all getting deleted afterwards anyway

#

I'll keep in mind for the future though that it's possible to get that number, thank you

river pilot
#

about your actual question: I think xdist (the parallelizing part) is separate enough from pytest that it doesn't know about fixture scopes, etc.

hexed meadow
#

interesting

#

that's definitely something you really need to be aware of

#

like, you could easily imagine a session level fixture that really does not work well to create multiple times

river pilot
#

is tempted to test this empirically

#

@hexed meadow a quick empirical test shows that each xdist worker runs the session-scoped fixture.

waxen portal
#

A = ["1", "2"]
A = ' '.join(A)
A1 = A.split(' ')[0]
A2 = A.split(' ')[1]
A3 = '1'
A5 = '2'
A4 = A1 if A3 == A1 else None
A6 = A2 if A5 == A2 else None
A4 = A4 if A4 is not None else ''
A6 = A6 if A6 is not None else ''

A7 = A4 + A6
print(A7)
Did smthin wrong ?

proud nebula
proper wind
proper wind
#

Is it a homework assignment?

waxen portal
#

Yes

#

Explain help me some

sleek tangle
#

I have a very weird problem. I am implementing a Python tool that generates some Python code as a string. When writing the tests, I noticed something very odd. For testing, I was generating multiple strings and asserting these can be interpreted by the Python interpreter. This will help me to detect if I am missing some imports or lines. However, I noticed that the same code leads to two different scenarios:

  • If I save the file and execute it via "python script.py" using subprocess (or even manually in the terminal), everything is fine
  • If I do exec(string) I get a NameError error saying that some variables do not exist. If I inspect the string I can clearly see these are defined. I can even execute the same script using python script.py. It just does not make sense

For more context, the file is just a collection of type aliases (some of them are nested). There are not any global variable and all imports are within the typing module

Any clue about what's going on?

#

Edit: I found something about compiling the code before if your program is a multi-line one. I never heard about it, gonna test it tomorrow

river pilot
sleek tangle
proud nebula
twin shale
#

Anyone used pytest with pytest-timeout plugin? Except for the detailed README, do you know if there are any gotchas to be aware of?

deft orchid
#

I am creating a flask application with several view functions. Should I test the rendered HTML template for the responses of view functions or, just their status codes (as I have seenn many projects do)? What is considered good? Thanks...

proud nebula
#

Ah. And checking the full output will suck :)

deft orchid
proud nebula
#

Bs4 to check parts imo.

deft orchid
hexed cloak
#

Smoke tests (just checking for status code) are better than nothing

hexed cloak
deft orchid
hexed cloak
#

You can check the flashed message shows up in the HTML your tests don't need to call render_template

deft orchid
#

Thanks

hexed cloak
#

You might want snapshot tests that render the HTML to a PNG and you commit what it's supposed to look like

deft orchid
proud nebula
deft orchid
hexed cloak
#

snapshot tests tend to change a lot

#

But are helpful for design review

twin shale
# hexed cloak snapshot tests tend to change a lot

If it's as easy to update a test as:
"this snapshot has changed, this is how it looked before and this is how it looks now. Accept the new look? [YES/NO]"
Then frequent changes I ought not be a problem

hexed cloak
#

Honestly this channel should be called just #testing

#

To cover smoke and snapshot and functional and unit tests

maiden pawn
#

it is a good name enough

#

if we stretch testing too much, it will be also Manual QA, e2e testing too much and etc

#

best to begin with unit testing πŸ˜› and then offtop everything else in same channel

twin shale
#

And test coverage, and random testing, and hypothesis

proud nebula
proud nebula
twin shale
#

Yes, I agree with you

proud nebula
#

<@&267628507062992896> can we rename this channel to testing? It's what it's actually about.

hollow basin
#

The channel is about automated testing in general, yes. If we change it to just "testing", people might not realize that we have a channel for pytest et al. Whereas I don't think people see "unit testing" and think "oh, I don't think I can ask about integration testing there"

proud nebula
hollow basin
#

When I said "a channel for pytest et al", I was referring to this channel, the one we are currently in.

proud nebula
normal lance
#

"testing" by itself might also suggest spamming or testing of discord features

proud nebula
#

Seems a but far fetched to me. But maybe yea.

proper wind
#

Can someone advice the best approach when you need to unit test functions that act on JSON data?
I have functions that process JSON data with a particular structure. Would I hard code what this JSON structure looks like into the unit test?

proud nebula
kind meadow
#

If the function accepts JSON as input then that's the function's public interface. I don't see an issue with the tests being aware of the input's JSON structure - they have to be in order to use the function. I wouldn't consider that "hard coding"

proper wind
# kind meadow What does the function actually do? The basic I approach I follow is testing fun...

Would you say it's always necessary to unit test every aspect of a project? Basically I am unit testing the core logic of my program but I am not bothering with testing the command-line interface aspect of it, as I'm using argparse and I know that unit testing the various errors can be difficult as it prints the error messages rather than raise exceptions. I'm also fairly confident in the argparse module catching any of the obvious errors.

maiden pawn
#

If isolation is zero, and amount of argparse is high => definitely should be tested

If isolated well or amount of argparse is small.. then almost no point to test

#

Essentially there is no point to unit test already tested framework
But if your code is too much intermingled, then testing framework (argparse) is the only way to test your custom code too

#

Unless u architectured better your own code

maiden pawn
# proper wind Would you say it's always necessary to unit test every aspect of a project? Basi...

I would recommend (since u have doubts to test it or not to test it) as minimal setup to unit test at least few argparsing related code invoking yours just for the sake of keeping in mind that u can write your code with ability to test it with integration to argparse if necessary in a future. And if u see no point to test today, then don't test it. Just keep writing with keeping in mind ability that u will be able to test it if it if u ever change your mind
Keeping this aspect in mind will keep code architecture within fixing easy reach to do it if desired. That allows making delayed decision about it.

proper wind
bitter wadiBOT
#

:incoming_envelope: :ok_hand: applied timeout to @flat fiber until <t:1711640519:f> (10 minutes) (reason: duplicates spam - sent 4 duplicate messages).

The <@&831776746206265384> have been alerted for review.

tight wyvern
#

hello guys

#

look at my new i think finished project

#

the chat budy

#

buddy

#
from websockets.sync.client import connect
import json
print("ChatMate")
def main():
    addr = input("address:")
    name = input("Nick:")
    with connect("ws://"+addr) as ws:
        ws.send("login "+name)
        while True:
            data = ws.recv()
            print(data)
            if data == "menu":
                print("1.Show Rooms")
                print("2.Disconnect")
                c = input(">")
                if c == "2":
                    break
                elif c == "1":
                    ws.send("list")
            elif data == "list":
                data1 = ws.recv()
                if data1 == "empty":
                    print("no rooms")
                else:
                    ls = json.loads(data1)
                    for x in ls:
                        print("room "+x["id"])
                while True:
                    print("1.join Room")
                    print("2.Add Room")
                    print("3.back")
                    c = input(">")
                    if c == "3":
                        ws.send("list")
                        break
                    elif c == "2":
                        name = input("Room Name:")
                        ws.send("mkrm "+name)
                    elif c == "1":
                        name = input("Room Name:")
                        ws.send("join "+name)
                        data = ws.recv()
                        if data == "succ":
                            while True:
                               ws.send("getchat")
                               data = ws.recv()
                               chat = json.loads(data)
                               print(data)
                               for mess in chat:
                                  print(mess)
                               msg = input(">")
                               if msg == "-e":
                                  break
                               ws.send("msg "+msg)
main()
#

its just a client that sends a message to a server that then gets put into a "room" (a list of messages) that people can read into

#

at the time im using ngrok for tunnelling

#

but if anyone has forwarded ports

#

i mean you could set up the server on your router directly

maiden pawn
maiden pawn
#

i am slightly confused though what to recommend πŸ€” the needed material i learned during first year of uni and not knowing good book to recommend for self studies

#

you need to learn... concepts of Functions, Classes... ah... i know

maiden pawn
river pilot
#

@maiden pawn you are prolific in this channel, I hope the wink means something positive.

#

because it's an unfortunate dynamic that some people who know things also think "tough love" is a good way to teach people stuff.

proud nebula
#

I don't see the big problem with the code. There are no variable names that lie and it's straightforward.

#

The biggest problem seems like it is that it should handle exit in a nicer way, like putting it as an option in the menu and/or handling ctrl+c.

proud nebula
hexed cloak
#

I'm not keen on the levels of idention, I'd be tempted to split each of the while loops into function calls with nice names

red anchor
#

Hello friends, I came across this useful article that helped me with a problem I couldn't overcome regarding Flutter. I think it may be useful for friends who encounter the same problem.

Dr. on Overcoming Challenges in Flutter Development Test Automation with Katalon Studio. Mehmet Fatih HarmancΔ±'s article: https://virgosol.com/tr/blog1/detay/flutter-test-otomasyonunda-karsilasilan-zorluklari-katalon-studio-le-asin

hexed birch
#

How to mock a class initialised outside the function

db=DB()
def func:
db.call()```

How to write unitest for this iam not able to mock DB object initialised outside. Please help me with this
proud nebula
#

Also, do you get an error or something?

runic bramble
#

Hi, does anyone have experience with unit testing in Python using unittest? I'm somewhat new to unit testing and I'm having trouble patching the gather method of asyncio πŸ₯Ή

river pilot
maiden pawn
# runic bramble Hi, does anyone have experience with unit testing in Python using unittest? I'm ...

i recently patched logging library method for silly reasons of injecting my tracing data into every logging record for any python app without touching their code ^_^

import functools
import logging
from typing import Any, Callable

from . import settings
from .data import get_trace_data


def _w_makeRecord(func: Callable) -> Callable:
    """
    Inspired by ddtrace.contrib.logging.patch._w_makeRecord
    """

    @functools.wraps(func)
    def wrapper(*args: Any, **kwargs: Any) -> Any:
        record = func(*args, **kwargs)

        data = get_trace_data()

        setattr(record, settings.RECORD_ATTR_SERVICE_NAME, data.service_name)
        setattr(record, settings.RECORD_ATTR_TRACE_ID, data.trace_id)
        setattr(record, settings.RECORD_ATTR_SPAN_ID, data.span_id)
        return record

    return wrapper


def patch() -> None:
    """
    Patch ``logging`` module in the Python Standard Library for injection of
    tracer information by wrapping the base factory method ``Logger.makeRecord``

    Inspired by ddtrace.contrib.logging.patch.patch
    """
    if getattr(logging, "_apm_patch", False):
        return
    logging._apm_patch = True  # type: ignore

    logging.Logger.makeRecord = _w_makeRecord(logging.Logger.makeRecord)  # type: ignore[method-assign]
#

hehe, used decorator "manually" for that

maiden pawn
#

that's if having trouble using standard unittest.mock.patch thing

proud nebula
runic bramble
# river pilot that sounds like a tricky thing to patch. Can you link us to some code to look ...

this snippet is part of a fastapi route that im testing. Basically, getToken returns a jwt token (β€œtoken-string-blablabla”) and signXML returns an signed xml file. At my noob understanding, β€œreturn_value” specifies the value I expect from the original function (for example, if I have a function that returns 'hello', my return value for the mock would be something like mock_hello.return_value='hello') and what I understand the gather method returns a tuple with the results of the functions passed as parameters and that’s what im trying to simulate here.
Now, my problem is that seeing my log from docker I think im patching it wrong. In the same route I have two gather methods. But for now, I'm only interested in patching the first gather method. When I look at the Docker log, I see some error logs.
The first error log ('str' object has no attribute 'content') leads me to believe that my patch of gather is also used in the second gather method (? due to the line json.loads(response_api_url.content.etc).
But yeah, im pretty lost so any advice is welcome.

runic bramble
pearl cliff
pearl cliff
maiden pawn
#

i am not sure if u can easily install log handler into django logging to make the same...
...probably u can. i don't know how πŸ˜…

runic bramble
pearl cliff
#

but what are you actually trying to test here?

runic bramble
pearl cliff
#
def submit_request(client: httpx.Client, ...) -> Something:
    resp1, resp2 = await asyncio.gather(client.post(...), client.post(...))
    ...
#

or even better still, write one function to submit the request and another function to handle the responses from it, then you can test the 2nd function without any mocking or patching at all

#
def perform_requests(client: httpx.Client, ...) -> tuple[httpx.Response, httpx.Response]:
    return tuple(await asyncio.gather(client.post(...), client.post(...)))

def process_response_data(resp1: httpx.Response, resp2: httpx.Response) -> Something:
    ...

def run_requests(client: httpx.Client, ...) -> Something:
    resp1, resp2 = perform_requests(client, ...)
    return process_response_data(resp1, resp2)

so now you can test process_response_data as a "unit", and testing run_requests is now more of an integration test, just making sure you didn't screw up the handoff between units

#

likewise perform_requests becomes almost trivial, there's almost nothing to test anymore

runic bramble
#

But I still have a doubt, if you dont mind, do you think it's a good idea to patch the gather method, or is it a tedious process that's not worth it under any scenario? I'm not referring only to my example using gather, but to any other process where it's being used

pearl cliff
#

it's not necessarily tedious, as much as it's highly "invasive" and imprecise

#

it also tightly couples your test to the implementation of your application

#

what if you refactor to use asynio.TaskGroup?

runic bramble
gusty bay
#

Can anyone explain me how can i implement this in pycharm

#

And how it's work

proud nebula
gusty bay
proud nebula
gusty bay
#

Ok let me try

raven tusk
#

Guys quick question, can you write doctest for ABC classes just to show how to use the class and its methods, or do you have to do it just for the subclasses?

proud nebula
raven tusk
#

What's a concrete class?

#

Ohh I get what a concrete class is now. How would I go about creating a concrete class for a ABC in doctest?

#

By the way, if you write doctests for a ABC, when you subclass that ABC and only provide the definitions for the abstract methods without changing the parameter types, or return types, would the doctest be inherited, or would you need to create a duplicate docstring with a duplicate doctest included each time?

proud nebula
#

You can write any code you want.

raven tusk
#

Ok, so if I have the ABC, and I also have the concrete classes, where should I put the doctest?

#

The main reason I am trying to put it in the ABC one is to reduce duplicate docstrings.

#

Also, I think I may have confused you a bit, I have testers to ensure the codes run as expected, so I don't need doctest to run, I simply am considering it for documenting usage examples.

#

I hope that makes sense.

raven tusk
#

So, could I have doctest format just to show usages without getting errors since I am not running them?

#

i.e.,

    @abstractmethod
    def get_counts(self,
                   num_shots: int,
                   backend: Backend | None=None) -> dict:
        """ Get the counts of the circuit.

        Parameters
        ----------
        `num_shots` (int):
            The number of shots to run.
        `backend` (Any | Backend):
            The backend to run the circuit on.

        Returns
        -------
        `counts` (dict): The counts of the circuit.

        Usage
        -----
        >>> circuit.get_counts(num_shots=1024)
        >>> circuit.get_counts(num_shots=1024, backend=backend)
        """
        pass
#

I won't run doctest here for instance, it's just to show how to use the method.

#

Would this be fine?

river pilot
# raven tusk Would this be fine?

if you aren't running them, then you can do whatever you want. I don't think those examples you showed are very good though. You should show the return value if you keep them.

#

i'm not sure this function needs an example.

raven tusk
#

How should I know when to include usage example?

river pilot
#

or, it does, because it returns a dict. you don't explain the structure of the dict.

raven tusk
#

Is there a rule of thumb perhaps?

raven tusk
#

Should I include Return for the examples as well?

river pilot
raven tusk
#

I don't follow.

#

Apologies for being slow hehe.

river pilot
#

I don't understand what dictionary is being returned.

raven tusk
#

I see, so in this case I should include an example of what is returned?

river pilot
#

i don't want to say "in this case". I want you to see that you have a lot of syntax in this docstring, but not much actual information.

#

put yourself in the user's shoes: will they understand what they need to know from what you have written? Have you fully described the function?

raven tusk
#

I think I understand.

#

By the way, what should I do when there is no return?

river pilot
#

you should say "returns None" or something to that effect.

raven tusk
#

No no I get the annotation part, I meant the Usage documentation.

#

Like just

>>> obj.method()

?

river pilot
#

what you have now is how it looks if the function returns None

raven tusk
#

Yeah

river pilot
#

will your users know what "counts of a circuit" means?

raven tusk
#

Ok, I think I understand now, thank you so much sir!

raven tusk
river pilot
#

ok

proud nebula
raven tusk
#

I just wanted to documet usage examples, and liked the doctest style.

#

The >>> thing.

proud nebula
#

I've spent TONS of time getting my docs in one of my projects to be run as part of the test suite. I've cought many many errors that way.

raven tusk
#

True, but for my case I have both mypy and pytest checking everything, I don't know if there are any other errors that would be missed.

#

I mean, doctest just runs the method, which I have testers for that I run using pytest.

proud nebula
raven tusk
proud nebula
#
>>> 1 + 1
2

is the same as pytest

assert 1 + 1 == 2
proud nebula
#

You are not making sense here

raven tusk
#

No, just pytest.

#

I have a folder containing my tester .py files, which I run to check my code using pytest.

proud nebula
#

Then how are you testing the example code in the docstring?

raven tusk
#

I don't test that example exactly, I do check examples in my tester files though.

proud nebula
#

Having correct examples is GOOD. Having incorrect examples is BAD.

rocky comet
#

You can make your point without being condescending

#

doctest will try to run the code given. For those, you want to only show good code

proud nebula
rocky comet
#

If you're frustrated, then take a step back. Getting snippy with other users is not the behavior we want here

#

Sound good?

final tide
#

Hey! when using @pytest.mark.filterwarnings, how would I pass my own warning to ignore?
I tried doing @pytest.mark.filterwarnings('ignore::MyWarning') but that did not work

hexed cloak
hexed cloak
hexed birch
#

I have a file

from db import DB
db=DB()
def check():
   #code```
Here DB intialisation tries to connect to the database. I want to mock DB(). I tried @patch('check.DB,''), but iam not able to mock it. Share your valuable insights.
final tide
hexed cloak
#

Can you paste your actual code and test?

modest harbor
#

Has anybody used any tools to automatically generate unit tests for Python? I just tried ChatGPT and PyCharm/IntelliJ, which each produced their own version of 'kinda helpful, but not really'.

#

I see somebody mentioned pytest-doctest above, I'll take a look at that.

proud nebula
#

But it should be used to reduce typing, not to actually write any code.

bitter wadiBOT
#

:incoming_envelope: :ok_hand: applied timeout to @barren onyx until <t:1712340695:f> (10 minutes) (reason: duplicates spam - sent 4 duplicate messages).

The <@&831776746206265384> have been alerted for review.

barren onyx
#

heloo guys

waxen portal
#

Traceback (most recent call last): File "threading.py", line 1052, in _bootstrap_inner File "threading.py", line 989, in run File "serverweb-2.py", line 2615, in helo PermissionError: [Errno 13] Permission denied: 'emulator-5566.txt'

#

Why

hexed cloak
# waxen portal

You're not closing your files correctly there. You need to use with open(...)

hexed cloak
amber fulcrum
#

I have problems running pytest with coverage (for Codecov) in GitHub actions. It reports a segmentation fault from running pytest, but after the tests have completed and the coverage file is generated. The test suite works fine on my computer. A possible suspicion is mem usage, but I'm stuck on how to proceed. I couldn't find anything similar on Google. Is there anyone here that might help shed some light on how I might proceed?

river pilot
amber fulcrum
# river pilot try to simplify the situation. Are you using pytest-cov and codecov? Perhaps re...

I'm using pytest-cov and codecov (because I want to feed the data into Codecov). The error is here https://github.com/Laerdal/python-objdictgen/actions/runs/8590177138/job/23537359537, however the error message on the crash is rather short ....063d58.sh: line 1: 1833 Segmentation fault (core dumped) pytest --cov=objdictgen --cov-report=xml -p no:logging

GitHub

Python library to work with CAN festival objectdictgen files - Disable logging in pytest Β· Laerdal/python-objdictgen@47030ca

river pilot
amber fulcrum
#

Yes, attempting to disable cov now

amber fulcrum
#

Bisecting on actual GitHub action runs are slow πŸ˜› -- I point my suspicion at wxPython. Whenever the loading of wx is not a part of any of the tests it doesn't crash.

hexed birch
narrow wharf
#

DB seems good for that

pulsar wedge
#

hello folks. im trying to write unit tests for a compiler but i have to format the tokens onto 1 single line and unfortunately i wrote the tokens mimicking the main file structures. i dont know my unix command well but i want to take every tokens and space them by one whitespace all of them onto 1 single continous running line.

river pilot
pulsar wedge
#

cuz its for a lab im researching for in school and the way the author wrote it (using junit) needs the tokens to be one spaced, all on 1 line

#

so like right now its like this:

#
   ID(has_left) BECOMES FALSE SEMICOLON
   ID(has_right) BECOMES FALSE SEMICOLON
   RETURN TRUE SEMICOLON
   RBRACE

   PUBLIC BOOLEAN ID(SetRight) LPAREN ID(Tree) ID(rn) RPAREN LBRACE
   ID(right) BECOMES ID(rn) SEMICOLON
   RETURN TRUE SEMICOLON
   RBRACE```
#

basically all of that needs to be in 1 line, one-spaced in Line 1

haughty timber
#

hello, I need a little help with something, is anyone free to help me out here or in dms?

haughty timber
#

can I post the code here?

proud nebula
#

This doesn't sound like a unit test thing. Maybe use the help system instead. And yes post the code there. Always post code when asking for help.

hollow basin
#

pytest question: I have a resource that I want to be shared between all the tests in a given module. I don't want that resource to be re-created for every test (ie, not a regular fixture), as it takes a long time to create and isn't stateful. Is there a way to specify module-level setup and teardown?

maiden pawn
maiden pawn
hollow basin
#

@maiden pawn thanks!!!

maiden pawn
nimble oar
#

Hi! I am using unittest and MagicMock. I have function process_website(...) and I want it to return [{'ad_data': 'example'}]. But it returns <MagicMock name='process_website()' id='2397875500816'>. What am I doing wrong? Here is my setup:

@patch('src.sql_server_database.SQLServerDatabase')
@patch('src.scrapers.ScraperFactory')
@patch('app.get_external_model_id')
@patch('app.process_website')
def test_get_ads(self, mock_database, mock_scraper_factory, mock_get_external_model_id, mock_process_website):
    # Set up mocks
    mock_scraper = MagicMock()
    mock_scraper_factory.get_scraper.return_value = mock_scraper
    mock_database_instance = MagicMock()
    mock_database.return_value = mock_database_instance
    mock_get_external_model_id.return_value = 'external_model_id'

    # Define sample data
    request_args = {'MakeId': 2, 'ColorId': 3}  # Example request arguments

    # Mock process_website to return sample data
    mock_process_website.return_value = [{'ad_data': 'example'}]

    # Call the function to test
    result = app.get_ads(request_args)

And in get_ads() function I have:
print('processed website: ', process_website('')) which prints:
<MagicMock name='process_website()' id='2397875500816'>

marsh mauve
#

Try calling from the app namespace (app.process_website) so that you actually call it

nimble oar
tacit grotto
#

Hi

proper wind
#

Polars

molten escarp
#

I haven't posted this in a long while so I thought I would drop a reminder because its so easy for things to get forgotten:

If you want to quickly jump in and test them out, I have written a "batteries included" web stack called the "Heavy Stack" and it comes with a dev container config which you can use with GitHub Codespaces. Just create a codespace and jump to the example test. You can find that here: https://github.com/heavy-resume/heavy-stack/ The pytest hot reloader typically uses a Daemon launch config and that's already set up for you.

river pilot
molten escarp
river pilot
#

got it, thanks

proud nebula
molten escarp
#

Pytest has plugin hooks that run at different times. There's one that runs really early.

pearl cliff
molten escarp
pearl cliff
#

github wiki is a good option for quick and easy

#

can link to it as "Documentation" on pypi as well

molten escarp
#

It's a challenge. I've been working on "heavy resumes" which basically gives you a high level structure with expanding elements and cross references, and an AI agent you can ask questions. While working on it I had the realization that you could really do it for any "flat" document. Would be nice for libraries as well. Markdown is showing its age.

proud nebula
#

As long as you parse the data coming over the wire and throw errors on incorrect data type that sounds ok.

Your tests will be slower if you do it this way than if it's all in-process though.

#

You should verify that it is

#

I just think you will get tests that are 2x-10x slower than they would be if you didn't pass through all the API layers and network stack

#

still. A function call is going to be quite a bit faster

#

yea that's true

dawn frost
#
def validate_image_file(
    _ctx: click.Context, _param: click.Option, value: Path
) -> Path:
    """
    Check that file named by path has JPEG format.

    :param _ctx: Library context.
    :param _param: Command-line option parameter.
    :param value: Parameter value.
    :return: Validated parameter value.

    :raise click.BadParameter: File named by path does not have JPEG format.
    """

    # constants
    jpeg_mimes = ("image/jpeg", "image/jpg")  # second is non-standard
    jpeg_exts = (".jpeg", ".jpg")

    # attempt to determine format
    guess = filetype.guess(value)
    mime: Optional[str] = (
        guess.mime if guess is not None else mimetypes.guess_type(value)[0]
    )

    # check that format is JPEG
    if (
        mime is None and value.suffix not in jpeg_exts
    ) or mime not in jpeg_mimes:
        raise click.BadParameter("Input image file format must be JPEG")

    # success
    return value
#

if i want to unit test this, do i mock filetype and mimetypes stuff?

#

or do i just give it paths to files that i've specially crafted?

#

ok i'm leaning towards the latter, the former feels very brittle (the UT would rely on the specific way that i'm checking the mimetype)

#

unless someone here thinks that UTs should be brittle like that?

weary quarry
#

Why not give it legit values that pass and fail the test?

dawn frost
#

by legit values you mean give it paths to actual files, instead of mocking filetype and mimetypes, right?

weary quarry
#

Yeah. Using a fixture file or two will remove any of the flakiness that mocking will give you.

weary quarry
#

At face value, that sounds more like an integration or end-to-end test. Those are usually best in the deployment CI where they can take the time they take. Marking the test and only running it when requested is the way I'd go with it.

hexed cloak
#

In the S3 protocol the client sends the checksum

hexed cloak
#

You could send an infohash from your client to your server, then you'd be able to work out which chunk is wrong if the hash is wrong

grand estuary
#

hello

#

Can someone help me?

#

line 23, in <module>
flappy=Bird(100,int(screen_height/2))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
line 21, in init
self.rect.center={x,y}
^^^^^^^^^^^^^^^^

Where did I go wrong?

#

I need to make a Flappy Bird type game for my School project

dawn frost
#

you haven't shown an error to suggest that somepoint is wrong

#

also this is the unit testing channel thinkW

#

speaking of which...

#

I have 2 test functions, each with the code mock_stat.return_value.st_size = <some int value>

#

at the breakpoint, i run Path().stat().st_size

#

on the left function, it evaluates to the number, but on the right function, it's an instance of MagicMock

#

wtf?

grand estuary
#

Its TypeError: invalid rect assignment

#

Sory I just started my coding journey in the beginning of this month

dawn frost
# dawn frost

if i make the patch("pathlib.Path.stat") the second patch in the right function, that fixes it

#

so idk wtf

#

oh ig decorators go outwards

dawn frost
proud nebula
hexed cloak
dawn frost
#

and it doesn't need to have actual data

proud nebula
#

Or test that only via the fast path with a small file.

near monolith
proud nebula
hexed cloak
hexed cloak
tardy field
#

Im currently doing my first steps with python unit testing.
I could need some support on how to correctly mock database and api.
do you have any good documentation or maybe anyone whos available to join a call and show me whats good practice?

hexed cloak
tardy field
hexed cloak
hexed cloak
hexed cloak
tardy field
#

mysql

hexed cloak
#

And you're using sqlalchemy?

tardy field
proud nebula
tardy field
proud nebula
maiden pawn
#

and yeah, pytest-django already does it for you

proud nebula
#

Containers has got to be much slower than what pytest-django does.

drifting sorrel
# tardy field Im currently doing my first steps with python unit testing. I could need some s...

I never use a DB when writing and running unit tests, I don't think a unit test should do that. But maybe the responses for your question is about testing in general, and specifically Integration testing?

A unit test, in my opinion, should test the data and logic that is before-and-after the DB/IO calls - testing your code and not the DB integration. For Integration tests, you would probably want a Test-DB running in isolation as suggested. If the code touched by unit tests do some IO/DB things, you would want to mock those out, or patch, or using dependency injection. My preference would be to isolate the DB call in a separate function, and patch that one (i.e. a fake function returning data that is in control of the unit test). I usually do that with pytest and the monkeypatch feature.

proud nebula
winter spire
#

When should I use fixtures and when ordinary helper functions in pytest? Is code below OK?

@pytest.fixture
def get_page_and_expand(selenium):
    selenium.get(urls.ELEMENTS_CHECK_BOX)
    expand_icon = selenium.find_element(By.CLASS_NAME, "rct-icon-expand-all")
    expand_icon.click()    

def click_checkbox(selenium, *checbox_names):
    for name in checbox_names:
        checkbox = selenium.find_element(By.XPATH, f'//span[@class="rct-title" and text()="{name}"]')
        ActionChains(selenium).move_to_element(checkbox).click().perform()

def test_checkbox_check_all(selenium, get_page_and_expand):
    click_checkbox(
        selenium,
        'Notes', 'Commands', 'React', 'Angular', 'Veu','Public',
        'Private', 'Classified', 'General', 'Word File.doc', 'Excel File.doc')
#

Should I ALWAYS use only fixtures?

proud nebula
winter spire
#

great

#

exactly what I ment -> how to decide

hexed cloak
winter spire
proud nebula
#

If the order of execution matters and it's not just a dependency tree: functions

hexed cloak
stark rose
#

Hello I have an application that can calculate p value and display it on graph(statistics) it works as follows: It is made in python as an addin to Excel. In Excel, there is a Calculate button , which, when the opens a GUI into which he enters data And at the end of that, the GUI button is generated, then the distribution graph is generated based on the input parameters entered by the user. My problem is that i need to write a document about Verification and Validation of this software, and im completely lost. I need help or some inspiration how can i make Validation and Verification of this software. Could you help me with that? I posted it here because it is something with testing

stark rose
#

project in school to make that app and write about validation and verification as last chapter of documentation

proud nebula
stark rose
#

what kind of tests because i tested the app many times but the test were just trying for example if the output is corret number or graph or if i get error message if i input wrong character etc..

proud nebula
maiden pawn
#

So we could be sure we help with smth u a actually asked about

#

As far as I remember my student years verification and validation were usually screenshots of program working and checking with smth its correctness by adding words if necessary

#

U could try selling unit/automated tests as alternative instead though... But i am not sure if your professors even know about unit testing existence. So not 100% sure if it is what they wish

stark rose
#

my professor definetely doesnt know about unit testing it doesnt have to be unity testing in my opinion i dont really know what.. I had to develop app that can calculate and display p value and the app should be working as Excel addin. And in word im writting about the process of making it. This 5 key things should i add to my work(writting): 1. Describe the general principles of hypothesis testing.
2. Perform an analysis of current software solutions for p-value calculation and display.
3. Design and implement an application that will calculate and display the p-value for selected hypothesis tests and be executable as an Excel add-in.
4. Verify and validate the created application.
5. Evaluate the contribution of the created application. I dont know how it is in your country its like bachelor thesis

#

and i have everything but the validation and verification i am stuck on this and dont know how to formulate it

maiden pawn
#

Add to screenshots optionally some wordings/formulas proving it shows correct working.

maiden pawn
#

good student... is sneaky student πŸ˜„

manic belfry
#

is there a way to force pytest's capsys to behave the same as when -s is passed in the CLI?

winter spire
#

How do I test those links in Python Selenium?
https://demoqa.com/links
<a id="created" href="javascript:void(0)">Created</a>
Do I need requests?

winter spire
#

check if links respond with corresponding statuses

proud nebula
winter spire
#

actually I don't care what it is :p.. so how to test this api call

proud nebula
winter spire
#

This is what I have just tried.
Getting TypeError: window.performance.getEntriesByType(...)[0].response is undefined

def test_elements_links_created(selenium):
    selenium.get(urls.ELEMENTS_LINKS)
    link = selenium.find_element(By.ID, "created")
    link.click()
    # result_output = selenium.find_element(By.ID, "linkResponse")
    WebDriverWait(selenium, 30).until(
        EC.text_to_be_present_in_element(
            (By.ID, 'linkResponse'),
            "Link has responded"
        )
    )
    status_code = selenium.execute_script("return window.performance.getEntriesByType('navigation')[0].response.status")
    status_text = selenium.execute_script("return window.performance.getEntriesByType('navigation')[0].response.statusText")

    assert status_code == 201
    assert status_text == 'Created'
winter spire
#

navigation entry has only diagnostic performance data 😦 😦 😦

winter spire
#

Any ideas?

hexed cloak
winter spire
winter spire
#

So I guess it is testable

lavish wren
#

Hi guys

#

i use unittest

#

never dive too deep on pytest, only in some open source gigs

#

what are you thoughts on each?

proud nebula
maiden pawn
maiden pawn
# lavish wren what are you thoughts on each?

my favourite feature is easy controlling scope of fixture reusability in pytest. besides for every test, calling for every module scope, or only once for session
Really powerful stuff to speed up tests

#

also simplified "assert" rules

proud nebula
#

hammett has lower overhead than pytest and is compatible to a tiny degree :) (I'm the author)

maiden pawn
#

pytest has entire ecosystem today πŸ˜› for example pytest-django with its awesome features to assert amount of SQL queries by its ORM

#

or pytest celery integration to have in memory celery worker stuff

lavish wren
#

yeah, that was my ideia of it after spending the whole week at work writing unitest tests

#

would prefer pytest for sure

lavish wren
maiden pawn
#

very rarely used pytest feature though

proud nebula
#

I think it's weird to do that. If you want to group, use files.

maiden pawn
#

This approach is also great if u generate documentation via sphinx also

#

relevant tests serving as code examples can be embedded into generated docs as entire file contents

bitter wadiBOT
#

:incoming_envelope: :ok_hand: applied timeout to @woeful terrace until <t:1714949266:f> (10 minutes) (reason: duplicates spam - sent 4 duplicate messages).

The <@&831776746206265384> have been alerted for review.

halcyon sigil
#

!unmute 879218993544720424 Please don't say hi in random channels, these all have specific discussion topics. I'd suggest #python-discussion or one of the off-topic channels

bitter wadiBOT
#

:incoming_envelope: :ok_hand: pardoned infraction timeout for @woeful terrace.

winter spire
#

How can I override/monkeypatch/decorate selenium.get() method in fixture so it reloades page if there is 502 Bad Gateway in page's source?
What do you think about this idea?

@pytest.fixture
def selenium(selenium):
    selenium.implicitly_wait(10)
    selenium.maximize_window()    
    return selenium

This is example of my .get() usage (I start the most tests with it)

def test_dynamic_properties(selenium):
    selenium.get(urls.ELEMENTS_DYNAMIC_PROPERTIES)
    text = selenium.find_element(By.XPATH, '//p[text()="This text has random Id"]')
    enable_after_btn = selenium.find_element(By.ID, "enableAfter")
    color_change_btn = selenium.find_element(By.ID, "colorChange")
    color_change_btn_class = color_change_btn.get_attribute("class")
#

Or is there some better way to handle this 502 for all tests?

winter spire
#

mistake 😦 thought driver.get() returns root element

shy ridge
#

Can anyone please tell what changes should I make in order to make it work in this way :
addressIn gets executed,
if unserviceableAddress is found
use addressRe to do the following - convert the pincode into an int, add 1 to it, and then convert it back to string, and use it like addressIn
if unserviceableAddress is found again, print -- doesn't deliver at your location
and if unserviceableAddress is NOT found, print delivery available, execute blinkSearch()

#
while True:
    pincode = input("Enter Pincode : ")
    if pincode.isdigit():
        break  
    else:
        print("Invalid Pincode. Please enter only digits.")
productName = input("Enter Product Name : ")
driver = webdriver.Firefox()
driver.get("")
driver.implicitly_wait(2)
def addressIn():
        addressBar = driver.find_element(By.XPATH, '')
        addressBar.clear()
        typeSim(addressBar, pincode[:3])

        reAddressBar = driver.find_element(By.XPATH, '')
        typeSim(reAddressBar, pincode[-3:])

        addressSuggestion = driver.find_element(By.XPATH, '')
        addressSuggestion.click()
def addressRe():
       pincodeRe = int(pincode)
       pincodeRe = pincodeRe+1
       pincodeRe = str(pincodeRe)
       
       addressBar = driver.find_element(By.XPATH, '')
       addressBar.clear()
       typeSim(addressBar, pincodeRe[:3])

       reAddressBar = driver.find_element(By.XPATH, '')
       typeSim(reAddressBar, pincodeRe[-3:])
       addressSuggestion = driver.find_element(By.XPATH, '')
       addressSuggestion.click()
def unserviceableAdressLocated():
       unserviceableAddress = WebDriverWait(driver, 3).until(  
      EC.presence_of_element_located((By.XPATH, '')))
addressIn()
reAttempts = 1
for _ in range(reAttempts):
     try : 
      unserviceableAddress = WebDriverWait(driver, 3).until(  
      EC.presence_of_element_located((By.XPATH, '')))
      addressRe()
      if unserviceableAdressLocated():
             print("Sorry, -- doesn't deliver at your location.")
             driver.quit()
             break
     except (TimeoutException, NoSuchElementException):
               print("Delivery available at your location, fetching relevant results...")
               blinkSearch(driver)
proud nebula
shy ridge
#

apologies if my query isn't clear, lmk and i'll try to reframe it.

proud nebula
shy ridge
# proud nebula Still not clear. You have a big function. Which part is the problem?

i doubt if the function is directly causing problems. the issue lies in the exception handling part

addressIn()
is supposed to return unserviceableAddress()
if the element unserviceableAddress() NOT found, then blinkSearch() must execute.
and if unserviceableAddress() is found,
then addressRe shall execute once,
if unserviceableAddress() is found again after the execution of addressRe
it should print "doesn't deliver to your location"
and exit

proud nebula
shy ridge
#

if the element is not found, this means that the address is serviceable and we can proceed with the other operations

#

but
if we find that element which says that the address is unserviceable, we try to manipulate the pincode, and retry entering the address ONCE using reAddress

and if we get that element again, we give up and print the error message

proud nebula
#

yea, you are again talking about a thousand things

#

which LINE is the problem NOW? just ONE line

shy ridge
#

the for loop and try except block

proud nebula
#

no, that's many things. ONE thing

shy ridge
#

try except block

proud nebula
#

You said the problem was with addressIn. There is no try/except in there. Also, I said ONE LINE, you said "the block"

#

And you still haven't said anything about any problem.

#
#

Please read that

proud nebula
# shy ridge sorry for being vague.

No need to apologize. This is normal when you are a beginner. I'm trying to show you how to think to be able to ask a good question. If you learn this, you can get help fast. Often you can even solve the problem yourself.

shy ridge
proud nebula
shy ridge
shy ridge
#

yes, and the code stops at that point because nothing happens past that.

proud nebula
#

typeSim(addressBar, pincodeRe[:3]) <- this is the line that is not filling in the data?

#

I asked you above for ONE line. Is this the line?

proud nebula
shy ridge
proud nebula
#

How do you know?

shy ridge
#

and the xpath of the element remains same so it definitely finds the element

proud nebula
proud nebula
shy ridge
proud nebula
shy ridge
proud nebula
shy ridge
# proud nebula What happened when the xpath was wrong?

it tried to proceed with the next function but gave hell lotta errors because the element where the next function is supposed to enter text didn't load (this sounds complicated af, but in my understanding it worked like it's supposed to)

proud nebula
shy ridge
proud nebula
shy ridge
#

so it broke

proud nebula
proud nebula
#

Ok, so moving on...

proud nebula
shy ridge
proud nebula
shy ridge
#

and it's compulsory to select the address from the dropdown menu

proud nebula
shy ridge
proud nebula
shy ridge
proud nebula
shy ridge
#

yes

proud nebula
#

do you know what "character" means?

shy ridge
#

do you "get" any (you mean get as in)?

#

i do

proud nebula
#

ok, so you try to type say "foo".. do you end up with "f"? "fo"? "foo"? or just ""?

shy ridge
#

foo

proud nebula
#

what?!

#

This discussion is some monty python sketch

proud nebula
shy ridge
#

i didn't read it properly 😭

proud nebula
#

Well.. that was a wasted hour

#

Ok, so I still have no idea what the problem is. After 2 hours. No idea.

#

Do you see how this is a problem?

shy ridge
sick arch
#

hey guys, beginner dev here

#

I've been stuck with this test for an entire day, relatively complex function (for me) and beginning to waste my time

#

mocking is a huge time sink. At what point do you just move on?

#

I often feel it would be much simpler to remove mocking and just test every single thing in real-world, it would simplify some things a lot

hexed cloak
#

Eg by separating IO from business logic

#

But sometimes it's better to write a small test that does real IO

proud nebula
#

Testing is a tradeoff. Don't treat 100% coverage as a religion, you will make life miserable.

sick arch
#

Thanks guys for replying

hexed cloak
#

I'd prefer a suite of small integration tests over large unit tests

sick arch
#

last app I did I spent sometimes days trying to pass one or two tests, and while this really ironed out most of the things, I was really miserable

hexed cloak
#

What's the system under test?

sick arch
proud nebula
#

I have zero mocks in my current code base. 3 years building it full time solo. ~50k dry lines.

sick arch
#

think I'll remove mocking for this one

hexed cloak
sick arch
#

and see how it goes

sick arch
#

the moment complexity popped up in central modules I was way over my head

hexed cloak
#

What did your mocks look like?

#

Celery has a test mode (always eager) that you can use

sick arch
#

I'm actually right now trying to test a celery task

hexed cloak
#

I see

#

Sometimes when testing against redis I use redislite

sick arch
#

gotta get back to it now honestly, getting a bit tired as it is

#

time is precious

#

thanks for the advice

proud nebula
sick arch
#

I can, I just am not familiar with mocking Redis to avoid connection, plus some functions aren't being called

#

and because I mocked REdis, Celery, some other connection, some other celery task, and it's all just a complicated bunch πŸ™‚

#

my biggest issue is when to actually make a change in the codebase and whether I did it just to pass the test, or is it an actual improvement..

proud nebula
sick arch
#

I suppose. I wanted to test some handling in a few error cases first

#

but I realize now that may not be the best thing to get to MVP any time soon

#

it's just a very complicated module, for me. It's a bunch of Celery tasks, which is all relatively new to me

maiden pawn
proud nebula
#

Maybe you don't need/want celery at all too heh. I think most people don't really, they just want a better cron.

maiden pawn
#

having programmatic cron as a code with single entrypoint for application is really cool πŸ˜›

#

better than having an array of entrypoints

#

i think as better solution we can be only having just for loop second thread... that works great in languages that have real parallelism at least.
subprocess can work in python though pretty fine (without shared memory, but oh well, at least like this)

proud nebula
#

Works very well for me.

maiden pawn
#

programmatic cron but just customized standartized to a library ^_^

#

taking care of all boilerplating

#

logical next step if doing customizations regarding that too many times

maiden pawn
# proud nebula Maybe you don't need/want celery at all too heh. I think most people don't reall...

The only little flaw with this logic is... mm...
your Urd is perfect for you, you are maintainer of it πŸ˜„ so u can be sure it is 100% perfect fit for you and author(you) will adjust it for you.

Celery makes sense to choose for him because it has solid team of devs maintaing it and he can be sure it will be maintained as well.

at a level of how Urd is having small team of contributor, it will make sense for him to choose it only if he will like its code and will feel confident in ability to write Pull Request / Fork it and continue its development on his own if necessary.

Otherwise... may be a point to write his own "Urd"

proud nebula
#

imo you want a scheduler, and then bring your own queue.

#
def some_task():
    for thing in Thing.objets.filter(something=3):
        update_thing(thing)

much more robust, simple, maintainable

proud nebula
#

But yea, Urd is tiiiiiny. And MIT or some such license. Can fork it and make it private for all I care.

shy ridge
proud nebula
azure crescent
#

yo

sudden stump
# sick arch I suppose. I wanted to test some handling in a few error cases first

Depending on the testing framework you use, you can mock celery. For me, I used unittest and was able to setup celery tests in the setup Class and teardown class and the mocked the actual celery function to return none then manually called the celery function within the rest case, awaited it's response and was able to test it. That's a long process but if you still need it tested that is a probable approach

#

And depending on whichever framework you are using, mine was Django and I had to use a Transaction Test Case instead

sick arch
#

I just want to test this as soon as possible and move to real-world testing, and integration testing. It's taking a lot of my time

sudden stump
sudden stump
ripe iris
#

Not sure what I am doing wrong but for some reason assertions are not failing the test for me.

I am writing unit-tests for an existing project and running everything at once like so:

# Run osc unit tests
osc_test_suite = unittest.TestLoader().discover('unit_tests/osc_tests')
unittest.TextTestRunner().run(osc_test_suite)

# Run RTMP unit tests
rtmp_test_suite = unittest.TestLoader().discover('unit_tests/rtmp_tests')
unittest.TextTestRunner().run(rtmp_test_suite)

# Run utility unit tests
utility_test_suite = unittest.TestLoader().discover('unit_tests/utility_tests')
unittest.TextTestRunner().run(utility_test_suite)

osc_test_suite, rtmp_test_suite runs fine but I am having issues with utility_test_suite. It is able to discover all 16 tests within it and it also running them. I have verified both by printing the same. I have also verified the assertion that's supposed to fail is not equal but printing it.

Not sure where I am going wrong and would appreciate some help.

One interesting thing. While running tests, for utility_test_suite it's not logging the (......):

poetry run python3 run_unit_tests.py
.............
----------------------------------------------------------------------
Ran 13 tests in 0.008s

OK
.......Exception in socket.connect(): 
..Exception in socket.connect(): 
...................................................
----------------------------------------------------------------------
Ran 60 tests in 2.548s

OK
Name                                               Stmts   Miss  Cover
----------------------------------------------------------------------
river pilot
river pilot
ripe iris
#

we needed coverage so we ended up running unittests like so:

# pip install coverage

import unittest
import coverage


# Start code coverage
cov = coverage.Coverage()
cov.start()

# Run osc unit tests
osc_test_suite = unittest.TestLoader().discover('unit_tests/osc_tests')
unittest.TextTestRunner().run(osc_test_suite)

# Run RTMP unit tests
rtmp_test_suite = unittest.TestLoader().discover('unit_tests/rtmp_tests')
unittest.TextTestRunner().run(rtmp_test_suite)

# Run utility unit tests
utility_test_suite = unittest.TestLoader().discover('unit_tests/utility_tests')
unittest.TextTestRunner().run(utility_test_suite)

# Stop code coverage
cov.stop()
cov.save()

# Generate code coverage report
coverage_percent = cov.report()

# Fail if total code coverage is less than 90%
assert coverage_percent >= 90, f"Code coverage is {coverage_percent}%. Minimum required is 90%."

# Generate code coverage HTML report (optional)
# cov.html_report(directory='unit_tests_coverage_report')

hence not using python -m unittest discover

river pilot
ripe iris
#

just wasn't aware of doing it this way since the existing implementation was working just fine until now. Will try this way now, thanks πŸ™‚

river pilot
ripe iris
river pilot
ripe iris
#

good ol print('xyz'), did it for a few tests and it showed up

#

coverage run -m unittest discover -s unit_tests/utility_tests; coverage report --fail-under=90;

this works! but still would be nice if I could make it work in the existing way

river pilot
ripe iris
#

oddly enough, I moved 3rd suite to 1st position and now it works. No clue why, how, etc

river pilot
proud nebula
ripe iris
#

Example:

self.assertEqual(result.message_code_str, 'PHONE_COMMAND_GET_FILE_LISTTTT')

Here, result.message_code_str is PHONE_COMMAND_GET_FILE_LIST still it won't raise assertion

proud nebula
#

I feel like you're showing way too much code, making it impossible for anyone else to reproduce it

ripe iris
#

ok, let me check

#
    def test_reproduct(self):
        print('reproduct start')
        self.assertEqual(0, 1)
        print('reproduct end')

Something interesting:

----------------------------------------------------------------------
Ran 60 tests in 2.573s

OK
reproduct start
Name                                               Stmts   Miss  Cover
----------------------------------------------------------------------
insta360/osc.py                                       88     27    69%

reproduct end didn't show up, so test got executed and failed but didn't show up on console for some reason?

proud nebula
#

I don't remember how unittest works. How does it normally look on failed test?

ripe iris
# proud nebula I don't remember how unittest works. How does it normally look on failed test?

something like this:

...........reproduct start
F
======================================================================
FAIL: test_should_fail (test_packet_analyzer.TestPacketAnalyzer.test_should_fail)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/avi/Development/Upwork/insta360/unit_tests/utility_tests/test_packet_analyzer.py", line 55, in test_should_fail
    self.assertEqual(1, 2)
AssertionError: 1 != 2

----------------------------------------------------------------------
Ran 12 tests in 0.009s

FAILED (failures=1)
.............
proud nebula
ripe iris
#

it works the same way without it

#

for now, I have just put that suite at the top and everything seems to work again

night arrow
#

Im currently working on a django project and I’m trying to test features by using pytest, every time I run pytest this error come up, can someone help me please. `=================================================ERRORS==================================================
__________________________________ ERROR collecting appsauthstests.py___________________________________
env/lib/python3.10/site-packages/django/apps/registry.py:158: in get_app_config
return self.app_configs[app_label]
E KeyError: 'auth'

During handling of the above exception, another exception occurred:
env/lib/python3.10/site-packages/django/contrib/auth/init.py:188: in get_user_model
return django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False)
env/lib/python3.10/site-packages/django/apps/registry.py:208: in get_model
app_config = self.get_app_config(app_label)
env/lib/python3.10/site-packages/django/apps/registry.py:165: in get_app_config
raise LookupError(message)
E LookupError: No installed app with label 'auth'.

During handling of the above exception, another exception occurred:
apps/auths/tests.py:9: in <module>
User = get_user_model()
env/lib/python3.10/site-packages/django/contrib/auth/init.py:194: in get_user_model
raise ImproperlyConfigured(
E django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.User' that has not been installed`

proud nebula
night arrow
# proud nebula You don't have auth in installed apps?

Yes I do, `Setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_simplejwt.token_blacklist',
'rest_framework.authtoken',
'drf_yasg',
'apps.auths',
'apps.socialAuths',
'apps.product',
'colorfield',
]

AUTH_USER_MODEL = 'auths.CustomUser’

model.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, max_length=100)
username = models.CharField(null=True, blank=True, max_length=100)
first_name = models.CharField(null=True, blank=True, max_length=100)
`

hexed cloak
night arrow
hexed cloak
#

It looks like you have a different settings module configured with pytest

#

What does your pytest config look like?

night arrow
hexed cloak
#

And how do you run pytest?

#

Show the full input and output

night arrow
# hexed cloak Show the full input and output

`(env) envCxntStop Server %pytest
=========================================== test session starts ===========================================
platform darwin -- Python 3.10.11, pytest-8.2.0, pluggy-1.5.0
django: version: 5.0.4, settings: main.settings (from ini)
rootdir: /Users/…/Server
configfile: pytest.ini
plugins: django-4.8.0
collected 0 items / 2 errors

=========== ERRORS ==========
______ ERROR collecting apps/auths/tests.py _______
env/lib/python3.10/site-packages/django/apps/registry.py:158: in get_app_config
return self.app_configs[app_label]
E KeyError: 'auth'

During handling of the above exception, another exception occurred:
env/lib/python3.10/site-packages/django/contrib/auth/init.py:188: in get_user_model
return django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False)
env/lib/python3.10/site-packages/django/apps/registry.py:208: in get_model
app_config = self.get_app_config(app_label)
env/lib/python3.10/site-packages/django/apps/registry.py:165: in get_app_config
raise LookupError(message)
E LookupError: No installed app with label 'auth'.

During handling of the above exception, another exception occurred:
apps/auths/tests.py:9: in <module>
User = get_user_model()
env/lib/python3.10/site-packages/django/contrib/auth/init.py:194: in get_user_model
raise ImproperlyConfigured(
E django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.User' that has not been installed
==== short test summary info =====
ERROR apps/auths/tests.py - django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.User' that has not ...

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
======= 1 errors in 1.32s ====`

hexed cloak
#

And what does tree show?

#

Ah

#

I think you called get_user_model too early. You should just use auths.CustomUser

night arrow
night arrow
hexed cloak
#

Show your code for apps/auths/tests.py

hexed cloak
night arrow
# hexed cloak Show your code for `apps/auths/tests.py`

`from django.contrib.auth import get_user_model
from django.test import TestCase
from rest_framework.test import APITestCase
from rest_framework import status
from django.urls import reverse

User = get_user_model()

class UserModelTestCase(TestCase):
def test_create_user(self):
user = User.objects.create(
first_name ='Test1',
last_name='Last1',
email='test@gmail.com',
username='Test123',
password='Test123',
date_of_birth='1995-12-16'
)
self.assertEqual(user.first_name, 'Test1')
self.assertEqual(user.last_name, 'Last1')
self.assertEqual(user.email, 'test@gmail.com')
self.assertEqual(user.date_of_birth,'1995-12-16')
self.assertTrue(user.is_active)
with self.assertRaises(ValueError):
User.objects.create_user(username='', email='', password='')
`

hexed cloak
#

Remember to use ```python

#

On line 9 you have a call to get_user_model()

#

Use auths.CustomUser instead

#

I think pytest-django only configures Django after collection

night arrow
#
from rest_framework.test import APITestCase
from rest_framework import status
from django.urls import reverse
from .models import CustomUser as User << like this ?

class UserModelTestCase(TestCase):
  def test_create_user(self):
    user = User.objects.create(
      first_name ='Test1',
      last_name='Last1',
      email='test@gmail.com',
      username='Test123',
      password='Test123',
      date_of_birth='1995-12-16'
    )
    self.assertEqual(user.first_name, 'Test1')
    self.assertEqual(user.last_name, 'Last1')
    self.assertEqual(user.email, 'test@gmail.com')
    self.assertEqual(user.date_of_birth,'1995-12-16')
    self.assertTrue(user.is_active)
    with self.assertRaises(ValueError):
      User.objects.create_user(username='', email='', password='')


If so new error 
================== ERRORS ================
__________ ERROR collecting apps/auths/tests.py ______
    from .models import CustomUser as User
apps/auths/models.py:1: in <module>
    from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
env/lib/python3.10/site-packages/django/contrib/auth/models.py:5: in <module>
    from django.contrib.contenttypes.models import ContentType
env/lib/python3.10/site-packages/django/contrib/contenttypes/models.py:139: in <module>
    class ContentType(models.Model):
env/lib/python3.10/site-packages/django/db/models/base.py:134: in __new__
    raise RuntimeError(
E   RuntimeError: Model class django.contrib.contenttypes.models.ContentType doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
========= short test summary info ============
ERROR apps/auths/tests.py - RuntimeError: Model class django.contrib.contenttypes.models.ContentType doesn't declare an explicit a...
tall brook
#

Check if you have missing migrations or db got out of sync with your models. I have found this problem and that's how I've fixed it

hexed cloak
#

Do you call django.setup() somewhere?

night arrow
hexed cloak
#

I guess try to make a MRE and we can try debugging that

#

What does main/settings.py looks like?

night arrow
#
import os
from pathlib import Path
from dotenv import load_dotenv
from datetime import timedelta


load_dotenv()

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework_simplejwt.token_blacklist',
    'rest_framework.authtoken',
    'drf_yasg',
    'apps.auths',
    'apps.socialAuths',
    'apps.product',
    'colorfield',
]

AUTH_USER_MODEL = 'auths.CustomUser'


MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'main.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
#
WSGI_APPLICATION = 'main.wsgi.application'

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=10),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=7),
}

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
    'NON_FIELD_ERRORS_KEY': 'error',
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),

    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ],
    'DEFAULT_THROTTLE_RATES': {
        'anon': '1000/day',
        'user': '500/day'
    }
}

# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get("DB_NAME"),
        "USER": os.environ.get("DB_USER"),
        "PASSWORD": os.environ.get("DB_PASSWORD"),
        "HOST": os.environ.get("DB_HOST"),
        "PORT": os.environ.get("DB_PORT"),
    }
}


# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]




LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

STATIC_ROOT = 'staticfiles'
#
import os
from .base import * # noqa
from dotenv import load_dotenv




# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get("SECRET_KEY")

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

hexed cloak
#

Just main/settings.py

#

Remember to use ```python

#

If you want to upload multiple files 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.

hexed cloak
#

@night arrow ^

night arrow
# hexed cloak Just main/settings.py
import os
from pathlib import Path
from dotenv import load_dotenv
from datetime import timedelta


load_dotenv()

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework_simplejwt.token_blacklist',
    'rest_framework.authtoken',
    'drf_yasg',
    'apps.auths',
    'apps.socialAuths',
    'apps.product',
    'colorfield',
]

AUTH_USER_MODEL = 'auths.CustomUser'


MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'main.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'main.wsgi.application'

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=10),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=7),
}
hexed cloak
#

Show the output from tree?

#

What's in settings/__init__.py

night arrow
# hexed cloak Show the output from tree?
β”œβ”€β”€ main
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ __pycache__
β”‚   β”‚   β”œβ”€β”€ __init__.cpython-310.pyc
β”‚   β”‚   β”œβ”€β”€ urls.cpython-310.pyc
β”‚   β”‚   └── wsgi.cpython-310.pyc
β”‚   β”œβ”€β”€ asgi.py
β”‚   β”œβ”€β”€ settings
β”‚   β”‚   β”œβ”€β”€ __pycache__
β”‚   β”‚   β”‚   β”œβ”€β”€ base.cpython-310.pyc
β”‚   β”‚   β”‚   └── dev.cpython-310.pyc
β”‚   β”‚   β”œβ”€β”€ base.py
β”‚   β”‚   β”œβ”€β”€ dev.py
β”‚   β”‚   └── test.py
β”‚   β”œβ”€β”€ urls.py
β”‚   └── wsgi.py
β”œβ”€β”€ manage.py
β”œβ”€β”€ pytest.ini
β”œβ”€β”€ requirements.txt
└── staticfiles
hexed cloak
#

Ah you're missing settings/__init__.py

#

What does your manage.py show?

night arrow
# hexed cloak What does your `manage.py` show?
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
from dotenv import load_dotenv

load_dotenv()


def main():
    """Run administrative tasks."""
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', os.environ.get('DJANGO_SETTINGS_MODULE'))
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)


if __name__ == '__main__':
    main()
hexed cloak
#

What do you have in DJANGO_SETTINGS_MODULE?

night arrow
hexed cloak
#

Basically you're pointing pytest at main.settings which is empty

#

you need to point it at main.settings.dev or test

night arrow
haughty tusk
#

Anyone experienced in php unit testing i need some help

proud nebula
gilded knoll
#

Anyone know how I can disable certain aspects of Pylint?

river pilot
gilded knoll
icy dust
#

hey quick question. i am new to coding and tried to code blackjack. its running but there is a problem. my ace is only worth 1 instead of either 1 or 11. my code is definitely not the best but hopefully you can help me with that

#

forgot to mention that its manly in german

proud nebula
proud nebula
covert heron
#

Hello guys,
for below piece of code
for file in list_of_files:
try:
shutil.move(src_path, dest_path)
except PermissionError:
print(f"Permission error copying {file} from {self.source_path} to {self.destination_path}")

How should I write a test in pytest? I come with this soultion:
def test_move_no_permissions(self, file_instance):
"""Test move method when user has no permissions in destination folder."""
os.chmod(file_instance.destination_path, 0o400)

I know there is no assert statement, but the test passes due to the except condition is catching PermissionError

proud nebula