#unit-testing

1 messages · Page 26 of 1

potent quest
#

with pdb

#

and pytest

#

bruh, my tests are easier to write than my code itself lmao

maiden pawn
#

yeah, you just need to pass few more arguments/flags to settings during selenium initialization

#
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--headless")
driver = webdriver.Chrome(executable_path="./chromedriver",
                              options=chrome_options)
lusty shore
#

Hello, could i get some resources to learn testing?

meager field
desert fulcrum
#

hey

#

I was trying to install pytest

#

check this out.

(base) feynman@legion-ayush:~$ pytest --version
bash: /usr/bin/pytest: No such file or directory

Its searching for pytest in /usr/bin

(base) feynman@legion-ayush:~$ pip install -U pytest
Requirement already satisfied: pytest in ./anaconda3/lib/python3.7/site-packages (6.2.5)
Requirement already satisfied: attrs>=19.2.0 in ./anaconda3/lib/python3.7/site-packages (from pytest) (21.2.0)
Requirement already satisfied: importlib-metadata>=0.12 in ./anaconda3/lib/python3.7/site-packages (from pytest) (3.10.0)
Requirement already satisfied: py>=1.8.2 in ./anaconda3/lib/python3.7/site-packages (from pytest) (1.10.0)
Requirement already satisfied: pluggy<2.0,>=0.12 in ./anaconda3/lib/python3.7/site-packages (from pytest) (0.13.1)
Requirement already satisfied: packaging in ./anaconda3/lib/python3.7/site-packages (from pytest) (21.0)
Requirement already satisfied: toml in ./anaconda3/lib/python3.7/site-packages (from pytest) (0.10.2)
Requirement already satisfied: iniconfig in ./anaconda3/lib/python3.7/site-packages (from pytest) (1.1.1)
Requirement already satisfied: zipp>=0.5 in ./anaconda3/lib/python3.7/site-packages (from importlib-metadata>=0.12->pytest) (3.5.0)
Requirement already satisfied: typing-extensions>=3.6.4 in ./anaconda3/lib/python3.7/site-packages (from importlib-metadata>=0.12->pytest) (3.10.0.0)
Requirement already satisfied: pyparsing>=2.0.2 in ./anaconda3/lib/python3.7/site-packages (from packaging->pytest) (2.4.7)

I seem to have pytest, but not in usr/bin

#

what do I do?

hexed cloak
#

It will be in your virtual environment

#

do which python?

desert fulcrum
#

(base) feynman@legion-ayush:~$ which python
/home/feynman/anaconda3/bin/python

#

its the one where pytest is

hexed cloak
#

Should be here then /home/feynman/anaconda3/bin/pytest

desert fulcrum
#

yeah

#

but when I say pytest --version

#

its not searching there

hexed cloak
#

What's your $PATH?

#

And deactivating and deactivating you virtual environment should do it

desert fulcrum
desert fulcrum
desert fulcrum
hexed cloak
#

(base) feynman@legion-ayush: looks like an activated virtual environment to me

desert fulcrum
#

i mean, its the default

#

its the one i use all the time

hexed cloak
#

echo $PATH I think

desert fulcrum
#

(base) feynman@legion-ayush:~$ echo $PATH
/home/feynman/anaconda3/bin:/home/feynman/anaconda3/condabin:/home/feynman/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

hexed cloak
desert fulcrum
hexed cloak
#

Sorry I typoed

#

uninstalling

desert fulcrum
#

ohh

#

is there a command for it

hexed cloak
#

/home/feynman/anaconda3/bin/python -m pip uninstall pytest
/home/feynman/anaconda3/bin/python -m pip install -U pip setuptools wheel

desert fulcrum
#

i uninstalled, and installed and it says the same thing lol

desert fulcrum
hexed cloak
#

Show the full output

desert fulcrum
#
Found existing installation: pytest 6.2.5
Uninstalling pytest-6.2.5:
  Would remove:
    /home/feynman/anaconda3/bin/py.test
    /home/feynman/anaconda3/bin/pytest
    /home/feynman/anaconda3/lib/python3.7/site-packages/_pytest/*
    /home/feynman/anaconda3/lib/python3.7/site-packages/pytest-6.2.5.dist-info/*
    /home/feynman/anaconda3/lib/python3.7/site-packages/pytest/*
Proceed (Y/n)? y
  Successfully uninstalled pytest-6.2.5
(base) feynman@legion-ayush:~$ /home/feynman/anaconda3/bin/python -m pip uninstall pytest
WARNING: Skipping pytest as it is not installed.
#

Now installing it again.

Collecting pytest
  Using cached pytest-6.2.5-py3-none-any.whl (280 kB)
Requirement already satisfied: toml in ./anaconda3/lib/python3.7/site-packages (from pytest) (0.10.2)
Requirement already satisfied: pluggy<2.0,>=0.12 in ./anaconda3/lib/python3.7/site-packages (from pytest) (0.13.1)
Requirement already satisfied: iniconfig in ./anaconda3/lib/python3.7/site-packages (from pytest) (1.1.1)
Requirement already satisfied: py>=1.8.2 in ./anaconda3/lib/python3.7/site-packages (from pytest) (1.10.0)
Requirement already satisfied: importlib-metadata>=0.12 in ./anaconda3/lib/python3.7/site-packages (from pytest) (3.10.0)
Requirement already satisfied: packaging in ./anaconda3/lib/python3.7/site-packages (from pytest) (21.0)
Requirement already satisfied: attrs>=19.2.0 in ./anaconda3/lib/python3.7/site-packages (from pytest) (21.2.0)
Requirement already satisfied: typing-extensions>=3.6.4 in ./anaconda3/lib/python3.7/site-packages (from importlib-metadata>=0.12->pytest) (3.10.0.0)
Requirement already satisfied: zipp>=0.5 in ./anaconda3/lib/python3.7/site-packages (from importlib-metadata>=0.12->pytest) (3.5.0)
Requirement already satisfied: pyparsing>=2.0.2 in ./anaconda3/lib/python3.7/site-packages (from packaging->pytest) (2.4.7)
Installing collected packages: pytest
Successfully installed pytest-6.2.5
(base) feynman@legion-ayush:~$ pytest --version
bash: /usr/bin/pytest: No such file or directory

Same issue

#

Oh and btw, import pytest is working

hexed cloak
#

What happens if you do

#

/home/feynman/anaconda3/bin/pytest

desert fulcrum
#
base) feynman@legion-ayush:~$ python
Python 3.7.11 (default, Jul 27 2021, 14:32:16) 
[GCC 7.5.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pytest
>>> 

desert fulcrum
# hexed cloak `/home/feynman/anaconda3/bin/pytest`

Weird stuff.

(base) feynman@legion-ayush:~$ /home/feynman/anaconda3/bin/pytest
Traceback (most recent call last):
  File "/home/feynman/anaconda3/bin/pytest", line 8, in <module>
    sys.exit(console_main())
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/_pytest/config/__init__.py", line 185, in console_main
    code = main()
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/_pytest/config/__init__.py", line 143, in main
    config = _prepareconfig(args, plugins)
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/_pytest/config/__init__.py", line 319, in _prepareconfig
    pluginmanager=pluginmanager, args=args
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/pluggy/hooks.py", line 286, in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/pluggy/manager.py", line 93, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/pluggy/manager.py", line 87, in <lambda>
    firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/pluggy/callers.py", line 203, in _multicall
    gen.send(outcome)
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/_pytest/helpconfig.py", 
#
line 100, in pytest_cmdline_parse
    config: Config = outcome.get_result()
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/pluggy/callers.py", line 80, in get_result
    raise ex[1].with_traceback(ex[2])
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/pluggy/callers.py", line 187, in _multicall
    res = hook_impl.function(*args)
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/_pytest/config/__init__.py", line 1003, in pytest_cmdline_parse
    self.parse(args)
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/_pytest/config/__init__.py", line 1283, in parse
    self._preparse(args, addopts=addopts)
#
 File "/home/feynman/anaconda3/lib/python3.7/site-packages/_pytest/config/__init__.py", line 1172, in _preparse
    self.pluginmanager.load_setuptools_entrypoints("pytest11")
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/pluggy/manager.py", line 299, in load_setuptools_entrypoints
    plugin = ep.load()
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/importlib_metadata/__init__.py", line 167, in load
    module = import_module(match.group('module'))
  File "/home/feynman/anaconda3/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
#
File "/home/feynman/anaconda3/lib/python3.7/site-packages/_pytest/assertion/rewrite.py", line 170, in exec_module
    exec(co, module.__dict__)
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/web3/__init__.py", line 6, in <module>
    from eth_account import (
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/eth_account/__init__.py", line 1, in <module>
    from eth_account.account import (  # noqa: F401
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/eth_account/account.py", line 11, in <module>
    from eth_keyfile import (
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/eth_keyfile/__init__.py", line 7, in <module>
    from eth_keyfile.keyfile import (  # noqa: F401
  File "/home/feynman/anaconda3/lib/python3.7/site-packages/eth_keyfile/keyfile.py", line 7, in <module>
    from Crypto.Protocol.KDF import scrypt
ImportError: cannot import name 'scrypt' from 'Crypto.Protocol.KDF' (/home/feynman/anaconda3/lib/python3.7/site-packages/Crypto/Protocol/KDF.py)
#

What does it have to do with Crypto.Protocol.KDF!

#

I googled that bit and that error only occurs to guys working with the web3 module

hexed cloak
#

!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 floppy disk icon in the top right, or by typing ctrl + S. After doing that, the URL should change. Copy the URL and post it here so others can see it.

desert fulcrum
hexed cloak
potent quest
#

how can i use a factory with return values on mocks?

pearl cliff
potent quest
#

ahhh, okay

#

trying to fully mock objects, as automatic as i can get it

#

onto type hinting to get them into side_effect

pearl cliff
#

it also depends on what exactly you're trying to do

#

"fully mocking objects" seems like a bad idea in a lot of cases

#

i prefer mocking as little as possible

#

but maybe you are doing mocking some enormous auto-geneated swig stuff and there's no sensible way to go about it otherwise

pearl cliff
hexed cloak
#

Like swing?

pearl cliff
#

it's a c++ binding generator

rancid timber
#

hey, i'm using pytest and travis-ci to test my github repo and forgot that dataclasses are not supported by python 3.6. i have searched the crawlers, the travis-ci docs, and read quite a few blogs, but feel like i'm missing something insanely simple. is there a way to install just the dataclasses module as a dep for only python 3.6 on travis-ci so that my tests can pass?

pallid radish
#

hello, I would like to test websites with python/selenium, what would you recommend me as library to manage those tests, generate reports etc .... thanks

#

pytest / unittest / robot ... ?

rancid timber
#

@pallid radish depends on your use case. i would recommend pytest though. i liked unittest, but it's very simple and web apps tend to grow in complexity and pytest scales with that complexity really well. alot better than unittest does. the difference is that w/ unittest, you'll have to manually implement alot of the stuff the pytest automates for you.

#

@pallid radish You might wanna read this discords help docs. they recommend against asking generalized questions and instead recommend asking very specific questions according to what you're asking. you're question is very general and hard to answer because, it just depends. its better to dyor on this one.

pallid radish
frigid basalt
#

Should tests be completely isolated? For example if I need to create a subclass, should this be done inside the test function?

glass quarry
#

@frigid basalt a unit test shouldn't reuse stuff from a previous test. (unless you're explicitly testing a scenario step-by-step and stopping when the first one fails, but that's not called a unit test any more)
If you find yourself creating the same stuff for many tests, instead of repeating yourself in each test function, you can create a "test fixture" with a setup method that will be run from scratch before each test method.
https://docs.python.org/3.9/library/unittest.html?#organizing-tests

frigid basalt
#

Hmm, thank you

pearl cliff
#

if you need to test something like a decorator, imo it's very reasonable to create the subclass right inside the test method

frigid basalt
pearl cliff
#

in my experience sometimes that's just the way things go. other times, if a test has a complicated setup, you can make a whole bunch of assertions in the same test method. it's not really a "unit" test anymore, but you are still testing individual units - just not as individual test methods

frigid basalt
#

I wanted to create it inside the file, since it essentially holds no state being clearly only a class

frigid basalt
# pearl cliff in my experience sometimes that's just the way things go. other times, if a test...

That's actually something I was considering asking about, I have a test like this: ```python
def test_non_registered(self):
"""Test that ValueError is raised when a listener isn't registered."""
class DummyEvent(Event):
name = 'DUMMY'

    dispatcher = EventDispatcher()

    async def callback(event: DummyEvent):
        ...

    with pytest.raises(ValueError):
        dispatcher.remove_listener(callback)

    with pytest.raises(ValueError):
        dispatcher.remove_listener(callback, event=DummyEvent)

    with pytest.raises(ValueError):
        dispatcher.remove_listener(callback, event=DummyEvent.name)
It seemed pretty dumb to copy this over for all of those. But yeah it's not *really* a unit test anymore
pearl cliff
#

meh, this is where i give the finger to formalism and just write the tests

#

but i also tend to write long-form comments explaining why i did things the way i did them

#

with my initials and the date at the bottom, so you can tell if it's out of date + people know who to message/email if there's a question

#

that said, in particular case you can set that up as a fixture, or just write a helper function to do it

#

but personally i'd probably write a test just like the example you posted

#

your'e still testing one unit of functionality imo

#

you are just making several assertions about it

#

you don't have to have 1 assertion per method

frigid basalt
pearl cliff
# frigid basalt How does that work? I am literally new to unit testing and trying to find my way...

one option that is very unittest-ey:

class TestEventDispatcher:
    def setUp(self):
        # A fresh DummyEvent class for each test method
        class DummyEvent(Event):
            name = 'DUMMY'
        self.DummyEvent = DummyEvent

        # A fresh EventDispatcher instance for each test method
        self.dispatcher = EventDispatcher()

    def test_non_registered(self):
        """Test that ValueError is raised when a listener isn't registered."""
        async def callback(event): pass
        with pytest.raises(ValueError):
            self.dispatcher.remove_listener(callback)
        with pytest.raises(ValueError):
            self.dispatcher.remove_listener(callback, event=self.DummyEvent)
        with pytest.raises(ValueError):
            self.dispatcher.remove_listener(callback, event=self.DummyEvent.name)
frigid basalt
#

Ah yeah like Zephyrite showed above

#

Isn't there a decorator?

pearl cliff
#

decorator for what?

frigid basalt
#

Isn't it called like parameterize?

pearl cliff
#

that's for pytest

#

and parametrize is not exactly the same thing, although you can think of it as an ad-hoc locally-defined fixture

#

a "fixture" is a general concept, although pytest has its very specific (and imo very weird and kind of unpleasant) notion of fixtures

#

i like almost everything else about pytest, but the fixture stuff is way too automagical for me, i'd rather have an explicit decorator for fixtures instead of relying on the parameter name

frigid basalt
#

Uh oh you said.. what?

#

It listens to the parameter name?

#

That's odd haha

pearl cliff
#

yes, pytest does that

#

no, i don't understand what the benefit is

frigid basalt
#

I just use the decorator way

pearl cliff
#

regardless, you don't need it in unittest

frigid basalt
#

How does it work there then?

pearl cliff
#

well, there's no unified framework for fixtures in unittest

#

you can use setUp() and setupClass() to set up test-scoped or class-scoped fixtures

#

and their corresponding methods tearDown() and tearDownClass()

frigid basalt
#

So you create your own decorators then?

pearl cliff
#

you could do that

#

you don't have to use a decorator

#

hypothesis and unittest.mock.patch can be used as decorators

unreal plank
#

probably so you can supply any set of args using rows of tuples

pearl cliff
#
@pytest.fixture
def foo():
    return 1

def test_something(foo):
    assert foo == bar()

pytest fixtures are like that

#

or something like that anyway

#

too magical for me, i'd rather explicitly write it out

@pytest.fixture
def foo():
    return 1

# hypothetical
@with_fixture(foo)
def test_something(foo):
    assert foo == bar()
proper wind
unreal plank
#

yeah it does work really well

plush vale
frigid basalt
#

Should I be testing all cases of my code and errors?

#

I can't help but feel like I am simply testing the implementation

#

Isn't there some saying that you should like "test the effect not the implementation"

maiden pawn
#

we test different branches of the code logic

#

===
plus sometimes we can think about the testing as just black box testing.
we don't know the code, we just input different edging input values and check the results, that's it

#

for example if your code allows as input values from 2 to 10. we tried 5, 0 and 12 to input and that's it. Whatever logic inside we don't care

#

===

#

and a third approach.
there is usually in your code separation between...

#

view logic, business domain logic and some implementation-low level logic

#

for example the most important to test business logic (the tests... are basically business scenarios), everything is else is usually less important.

#

===
black box testing is usually the easiest to be done and the most refactor resilient (after main code refactorizations, less changes to tests are needed) ;b

frigid basalt
#

Are code that tests good input better than code that test for errors or similar?

#

That's something I've run into, it feels like I am just creating tests to run the error-cases of bad behaviour

maiden pawn
maiden pawn
#

less attachements to implementations ->
-> less fragile tests ->

#

-> less refactorizations to testing code

pearl cliff
#

i've never regretted writing a test for a "good" input - if those tests break, then you really know you fucked up

maiden pawn
#

well, considering that error outputs are still error outputs... if we test input and output, we would test error outputs too

#

obviously... if there is something like a rule, that one email should not be able to register twice, we need to test registering with same email twice and checking for the error

#

we just input email twice ;b and check the output for error in this case

frigid basalt
#

It seems somewhat unnecessary to make tests for bad input?

#

It's not expected behaviour and all it does it reveal more of the implementation

#

To fully test my method I need to look at the implementation and write tests that reach each branch or execution

trim hill
#

Guys I need some help. Wrote a few unit test which detects if my sklearn model outputs the same number given the same seed and input

#

It works on my local machine, but when I went up to Microsoft Azure, the random numbers became different despite having the same seed

#

Does different machine create different floating point error or something?

#

TL Dr, unit test doesn't work across different machine despite having checked very thoroughly that they all have the same random state

maiden pawn
#

if those errors are important for business/domain logic of the application

#

then surely it is important to test them

#

although you know, it is better to test all errors that users will see 🤔

#

but the priority can be made for which ones are important and which less

magic dawn
magic dawn
#

or different OS

#

your test is way too granular

magic dawn
#

"tests can only show the presence, and not the absence, of bugs"

#

minimally you should write tests to show that the happy case, as well as a few expected "bad" cases, are handled correctly

#

but it depends on what level of testing you're performing

#

in general, @ very high levels (acceptance tests), what you care about is more that the user is able to do something

#

e.g. "can sign up for a class"

frigid basalt
#

Hmm, yeah

trim hill
#

Although, what would be a good example for what I should be testing? Perhaps something like "this algorithm does reduce feature to an expected amount"?

magic dawn
#

like unit, integration, contract, acceptance, E2E

north stratus
#

!code

#

for a give function:

def foo(self): 
  try
    bar()
  except

I'm supposed to write an unit test:
I've mocked the bar function and tested the foo. Caveat here being that I'm somehow supposed to trigger the except part, however, bar does not contain any raises. How can I achieve this, keeping in mind that bar is as of this time mocked?

fading needle
#

Hello all,

I was trying to make a profiler in Python and i ve failed many times until i ve finally got it with an offical CProfiler from the Python documentation.

I am using it as a decorator and i am obviously pasting it above each function that i want to profile, and the report that i get is too long and therefore i can not read it from the console.

Since every single profiler visualisation tutorial on the internet is running CProfiler from a console by running a file and not decorating it as i am doing it, i can not find a solution to make it, so i am here asking you for help.

Thanks so much in advance!

wise bolt
#

hey, im new at unit testing and i saw that there are 2 libs that i can use: pytest and unittest
id like to know which one of there two is considered the "best" in terms of documentation, clean code (if applicable), etc

umbral mantle
trim hill
# magic dawn like unit, integration, contract, acceptance, E2E

Only the first two. Unfortunately until the last month, I've been using python to perform statistical analysis and the standards in my team aren't very good as everything was at its starting stage. So initially there was absolutely no good practice. I'm trying to change this of course.

I only know unit test test the most basic functions. And integration test are how these function should behave when integrated together

#

My colleague introduced me to a simple example where I call a function with predefined input, and end that test with a assert np.isclose(result, expected_result)

#

So I've been using that mostly

#

Contract acceptance and e2e, I have only heard of that from you

#

Quick Google search gave me understanding of contract and E2E, though acceptance still sounds arcane to me

magic dawn
#

but if you are serious about it, I suggest doing (a lot of) research on "how to test" and "what to test"

frigid basalt
#

I am using pytest to test a mixin, and I want to run all tests on a few of the classes that implement this test. Which means tests may be ran multiple times

#

How would I create a fixture to do this?

#

I was considering using parameterize on the class-level to apply on all tests.. but that means that instances of the class is shared (unless I just pass the class I guess?)

#

Y'know, I'll probably just do that nvm

trim hill
trim hill
#

I just need more experience and mileage

wet crow
lethal crater
#

why is the unit test not running?

#

i have this structure

dusky dew
#

your test method needs to start with "test" iirc

#

cc @lethal crater

lethal crater
#

oh ok

#

thx

potent quest
#

Is it a bad thing when test files are 2x longer than the file they're testing??

normal lance
#

definitely not imo. you could probably do some refactoring for the test to reuse helper functions etc, and it is good that the implementation of a functionality is shorter, but it's rarely bad to test too much

cobalt ore
#

Do people typically write tests for properties of functions? Eg, we might want all functions written for a particular module to be idempotent - and to test that is the case. I'm wondering if there's a typical way to go about this sort of testing though, perhaps there's a name for testing the properties of functions and not just their behaviours

cobalt ore
#

I get that if i have something like:

def f(x):
    if x % 2 == 1:
        return x + 1
    return x

Then I could check idempotent with something like:

assert f(3) != 3
assert f(f(3)) == f(3)

not sure if there are standard approaches to this though

plush vale
#

I'm not sure regarding your first question, but I don't think you can check for idempotence while treating the func as a black box

#

consider:

>>> vec = []
>>> def add_one(n):
...   vec.append(n)
...   return n + 1
...
#

the state of the program changes every time you call this function, but it's not observable from the return value alone

magic dawn
#

actually most of my test files are longer than the implementations

magic dawn
#

it doesn't for example, talk about determinism (which was exactly the problem)

#

but in this case it's not really just that...

#

the question is - what are you really testing?

#

@ lower levels of integration and abstraction it's easy to say a function works or does not work

#

but what does it mean to say a model "works"?

#

if it's a language problem, does it make sense to assert bleu_score > 4.0?

trim hill
#

I definitely was testing for determinism.

It does test if all the underlying "random state" parameter are set to something and not a "None" value as well, which didn't fail. This test if it's default behaviour defaults to the one I intended it to be.

As for everything else, it wasn't really something under my control (it's sklearn model) so I didn't test those.

trim hill
#

I'm testing out RandomForestClassifier fyi

cobalt ore
potent quest
normal lance
#

if vec isn't used anywhere else it would be hard to spot by writing tests alone, unless you look into the code itself and check for themodule.vec from the test, but by looking at the code you'd probably spot the problem already. Either way, if you have linting it will probably warn you about something like this in most cases

haughty summit
#

Guys how do I setup a test database for backend tests with pytest and docker?

maiden pawn
rose oyster
#

for the others - Idk

tight geyser
#

django is so cool; I was fretting about how to do model tests but yeah, just change the db backend to sqlite and everything works the same

proper wind
#

you don't even need to change the db...if you're using something else, like postgres, it will create and tear down a test_database

tight geyser
#

true, but that requires a database already set up, so sqlite is useful in that case

proper wind
#

oh yea. I thought you meant you changed it for testing.

haughty summit
magic dawn
#

it's better to have your test env mirror your prod env as much as possible

maiden pawn
tight geyser
#

yes
in this project I had no control over our build infra, which did not have postgres (╯°□°)╯︵ ┻━┻

sinful hill
#

how y'all like my tests

#

it's for a function to count how many consonants & vowels are in a sentence lol

maiden pawn
sinful hill
#

Sir, it is a crime to neglect adding the diacritics in Padmé Amidala's name

#

It interferes with testing it's ability to handle diacritics

maiden pawn
#

no idea what it is, but I'll trust your words about it

sinful hill
#

é not e

maiden pawn
pearl cliff
#

@maiden pawn don't forget all 4 normalization forms!

pearl cliff
#
import unicodedata
from functools import partial

to_nfc = partial(unicodedata.normalize, 'NFC')
to_nfd = partial(unicodedata.normalize, 'NFD')
to_nfkc = partial(unicodedata.normalize, 'NFKC')
to_nfkd = partial(unicodedata.normalize, 'NFKD')

@pytest.mark.parametrize(
    "phrase ,constants_amount, vowels_amount", (
    ("Among Us", 3,4),
    (to_nfc("Padmé"), 2,3),
    (to_nfd("Padmé"), 2,3),
    (to_nfkc("Padmé"), 2,3),
    (to_nfkd("Padmé"), 2,3),
    ('', 0, 0),
    (['List'], 1, 3)
    )
)
def test_howmany_consonants_and_vowels_in_English_sentence(phrase, constants_amount, vowels_amount):
  assert vcc(English, phrase) == (constants_amount, vowels_amount)
maiden pawn
pearl cliff
#

!e ```python
import unicodedata
text = 'Padmé'
enc1 = unicodedata.normalize('NFC', text).encode('utf-8')
enc2 = unicodedata.normalize('NFD', text).encode('utf-8')
print(enc1)
print(enc2)

bitter wadiBOT
#

@pearl cliff :white_check_mark: Your eval job has completed with return code 0.

001 | b'Padm\xc3\xa9'
002 | b'Padme\xcc\x81'
maiden pawn
pearl cliff
#

yeah i imagine there's some tidy way to chain parameterizations, otherwise you can do it with itertools things or write your own helper functions

maiden pawn
#

@sinful hill

import unicodedata
from functools import partial

@pytest.mark.parametrize("normalization", ('NFC', 'NFD', 'NFKC', 'NFKD'))
@pytest.mark.parametrize(
    "phrase ,constants_amount, vowels_amount", (
    ("Among Us", 3,4),
    ("Padmé", 2,3),
    ('', 0, 0),
    (['List'], 1, 3)
    )
)
def test_howmany_consonants_and_vowels_in_English_sentence(normalization, phrase, constants_amount, vowels_amount):
  normalizator = partial(unicodedata.normalize, normalization)
  assert vcc(English, normalizator(phrase)) == (constants_amount, vowels_amount)
#

if it will work

pearl cliff
#

the former is "composed" and the latter is "decomposed"

maiden pawn
#

it is not me who does it

#

I just adviced about parametrization)

pearl cliff
#

👍

#

!e ```python
print('\u00e9')
print('\u0065\u0301')

bitter wadiBOT
#

@pearl cliff :white_check_mark: Your eval job has completed with return code 0.

001 | é
002 | é
sinful hill
#

Well, it's a crime to spell Padmé Amidala's name without the acute é...

#

Or at least it should be

proper wind
#

How do I access mappings when unit testing? I cant seem to figure it out

haughty summit
#

hey guys, I'm writing a few tests rn

def test_check_password(user: User, faker: Faker):
    """
    Ensure we can verify an user's password.
    """
    password = faker.password(length=12)
    user.set_password(password=password)
    assert user.check_password(password=password)
    assert not user.check_password(password="someotherpassword")

In this pytest test case (which uses faker), is there any way that I don't have to hardcode the "someotherpassword" string and still make the tests pass consistently?

frigid basalt
#

Generate another one with faker?

#

So do other_password = faker.password(length=12) but don't use the set_password()

pearl cliff
#

this is a great use for hypothesis

#
@hypothesis.given(st.text(), st.text())
def test_check_password(password, other):
    """Ensure we can verify an user's password."""
    hypothesis.assume(password != other)
    user.set_password(password=password)
    assert user.check_password(password=password)
    assert not user.check_password(password=other)
cosmic sedge
#

Hey, I am trying to test following scenario:

class Foo:
  def __init__(self, bar):
    self.bar = bar
  
  def do_stuff(self):
    self.bar.fun()

test attempt using unittest:

import unittest
import bar

class ATestCase(TestCase):
    def test_do_stuff(self):
      # given
      mock_bar = MagicMock()
      mock_bar.fun = MagicMock()
      test_foo = Foo(mock_bar)

      # when
      test_foo.do_stuff()
      
      # then
      mock_bar.fun.assert_called()

is there shorter way to mock attributes like mock_bar.fun? Ideally a one-liner

in js using jest it is possible to mock objects like const a = {fun: jest.fn()}, I'm looking for something similar

magic dawn
#

!e

from unittest.mock import MagicMock

a = MagicMock()

a.b.c.assert_called()
bitter wadiBOT
#

@magic dawn :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 5, in <module>
003 |   File "/usr/local/lib/python3.10/unittest/mock.py", line 888, in assert_called
004 |     raise AssertionError(msg)
005 | AssertionError: Expected 'c' to have been called.
magic dawn
#

yeah there we go

rocky ermine
#

When we write tests,is it the output we're testing for or the logic that brings the output? From the tutorials I've gone through (10+), It seems tests are concerned with the output. I'm new to this, and I've always thought it's the logic that's being tested and not the output.

hexed cloak
#

Or the side effects

#

@rocky ermine how would you test a function without looking at the output or side effects?

rocky ermine
hexed cloak
#

?

rocky ermine
#

I was basically rewriting the logic uniquely for the test, for whatever dumb reason I could think of.

#

the test class has a rewritten logic, which isn't the right way to go about it from what I've read. Thanks.

hexed cloak
#

Well that's something you can use in hypothesis

#

Eg if you're writing an optimal algorithm you'd compare it against a naive implementation

violet frigate
#

how to write a function that receive an image and returns the image in black and white using python np.average?

rocky ermine
#

How do I test a post endpoint without sending data from the post endpoint? I don't want to fill the dB with nonsense.

#

Most of the tutorials are testing get endpoints then mocking the data and response. Barely anything for post endpoints.

hexed cloak
#

Usually you'd roll back your database after each test

rocky ermine
#

I don't exactly have access to the dB. Everyone uses an API to read and write to the the dB.

#

If its not possible, I'll just tell them that we probably need mongo collection in the db for this kind of tests.

hexed cloak
#

Eh

#

That doesn't sound like a unit test

hexed cloak
cosmic sedge
#

I've just spend a few hours trying to figure out what is wrong with my test (already baseline scenario). It was failing when trying to run via python -m unittest foo.test.py on unittest library level with vague errors
It turned out it was because of filename, which included dot. When changed to foo_test.py it works correctly.

I tried to find such requirements in unittest docs, but I failed to find it. Can anyone help with finding reference?

mortal flare
mighty bluff
#

Is there a reason not to use unittest and instead go for a different, external package? Usually I try to stick with what Python gives me to be independent of external packages but maybe ther might be reason to use pytest or nose or something?

hexed cloak
mighty bluff
#

Is there a reason behind that @hexed cloak?

hexed cloak
#

pytest is better for mypy, for example

#

Generally if there's a pypi alternative of a built in you should use it and avoid the built in

proper wind
#

It's a great goal to have, that's for sure.

pearl cliff
#

my one complaint about pytest is the overly-magical fixture system... i wish you could request a fixture explicitly with a decorator, and turn off auto-requesting from parameter names

#

"explicit is better than implicit" basically

narrow cave
#

!e

def factorial(num, total=1):
    if num == 1:
        return total
    else:
        total*num
        factorial(num-1, total)

result = factorial(5)
print(result)
mighty bluff
#

Do you write docstrings for your tests?

pearl cliff
#

yes, pytest and unittest can report the docstrings in output

stiff atlas
#

Is there a way to have pretty graphs from running python -m unittest?

hexed cloak
maiden pawn
mighty bluff
kind meadow
#

I find that can get unreadable, so I rely on the docstring to get more information across while keeping the test's name light.

median kindle
#

Hiya! Is anyone 'round here familiar with the Factory-Boy library, and interested in helping to **proofread ** an article I wrote?

I'm a factory-boy noob and I spent a lot of time figuring out how to use it. I wanted to contribute to the pool of writing to help other new people learn it; I just finished my first draft yesterday :)

craggy canyon
#

Okay, I need help from someone with a Mac; -;

flint fiber
#

If I have a class:

class HTTPError(AblazeBaseException):
    def __init__(self, response: ClientResponse, *args) -> None:
        self.response = response
        self.status = response.status

        super().__init__(*args)
``` where its pointless to test because there just isnt really anything to test, is it ok in situations like this to tell coverage to ignore it, or is that a big no-no?
frigid basalt
flint fiber
frigid basalt
plush vale
#

you dont need to assert anything

hexed cloak
#

Can't you run some code that actually raises it?

potent quest
#

@flint fiber ^

dusky dew
#

I feel like asserting that it is subclassing the right parent is a bit too strict unless the exception is designed for application code or something

potent quest
#

depending on which test structure you use, a full test could be like this:

import unittest
import unittest.mock

class TestHTTPError(unittest.TestCase):
  def test_init(self):
    mock_response = unittest.mock.Mock()
    
    error = HTTPError(mock_response)
    
    self.assertIs(error.response, mock_response)
    
    with self.assertRaises(HTTPError):
      raise error

note: i use pytest, not unittest so this may not be accurate

hushed quartz
#

Hi there, I'm a newbie in unit testing, I have this method that opens the file and makes some conditions then generate the output, what I wanna accomplish is to test this method, but the thing that I can't understand is, how can I test it while it's a static method, not I dynamic, what I mean is, It just has one specific file and I can't pass a file to it, so can anyone give me a hint how can I test it!

hexed cloak
#

myfiel seems like a typo

#

Also it prints "Python" for every subsequent line once it finds it?

unreal plank
#

that's what ,i would do, then it would be very easy to test. you could easily parameterize it

#

i have to assume this is just a sample, not your real function

#

since it doesn't do what it claims to do and it would give an UnboundLocalError, I think

#

but if you're making something testable, you also want your functions to return their output instead of printing

#
def parseSQL(sql):
    output = ''
    for line in sql.splitlines():
        if line.find('Python'):
            output = 'Python'
    return output
unreal plank
# hushed quartz Hi there, I'm a newbie in unit testing, I have this method that opens the file a...
import pytest
@pytest.mark.parametrize(
   ('sql', 'expected'), [
       ('select * from spam', ''),
       ('delete from Python where 1 = 1', 'Python'),
   ]
)
def test_parseSQL(sql, expected):
    assert parseSQL(sql) == expected
def parseSQL(sql):
    output = ''
    for line in sql.splitlines():
        if line.find('Python') != -1:
            output = 'Python'
    return output
``` ...then, you would run in a command line:
```bash
python -m pytest yourfile.py
``` That should be a basically a working example, hopefully it answers your question of how you would test your function
hexed cloak
unreal plank
hexed cloak
#

Also it needs to print out for every line

#

Not return it

unreal plank
hexed cloak
#

Right but for every line

unreal plank
hexed cloak
#

The print happens for every line

unreal plank
#

my code is an example to show "how would I test this", it's not meant to be used verbatim

#

I'm sure t will need to be adapted

hexed cloak
#

It's not clear what the function is supposed to do, it seems like it has been modified from the source before pasting here

unreal plank
#

exactly what I said

#

it doesn't have anything to do with SQL

#

so I assume it's just a contrived example, but who knows...

unreal plank
#

DISCLAIMER parseSql() us not to be imitated 😂 😂

#

basically it should more accurately be named foo or baz

hushed quartz
#

Thanks guys

eager jay
#

Hey all

#

Is there a way of passing environment variables defined in tox into the actual python code that is being tested?

hexed cloak
#

Your grab it from os.environ

lunar cedar
#

(Asked in main help with no luck, so I'm posting here)
I'm looking to develop tests/examples (not strictly unit tests) for a package I'm writing. I'm using a virtual environment to run my tests, and that's where my package and it's dependencies are installed.
The directory structure is

repo/
    | -package_name/
        | -__init__.py (imports package_name.module_1 and package_name.module_2)
        | -module_1.py
        | -module_2.py (imports module_1.py)
    |-tests/
        |-test.py (uses the package and one or more of the modules)
    |-test_virtualenv/ (directory created by virtualenv)
    |-setup.py (for making PyPI package)

I create the virtual environment with virtualenv , install my package (which gets the dependencies) using the virtual environment pip -e install., then deactivate.
When I want to run my tests I activate the environment, then loop over and run the Python files in tests , which is when I get the error.

File ....../module_2.py, line 2, in <module>
    import module_1
ModuleNotFoundError: no module named 'module_1'

I can probably construct a simple failing case, but hopefully somebody could spot my issues before that. Thanks!

frigid basalt
#

That's because you actually have an issue in your package

#

You need to either do from package_name import module_2 or from . import module_2

lunar cedar
#

Thank you! This seems to mean that I can no longer run each of the module files of my package as standalone files (maybe I shouldn't have expected this in the first place?), which is a bit inconvenient for development. What's the proper workflow for this?

frigid basalt
hexed cloak
lunar cedar
#

@frigid basalt I find it convenient when developing (and I dislike notebooks). But it's good to know I can't have it all, as that was my expectation.
@hexed cloak Yep, that works for my case, thank you!

hexed cloak
#

Then I put it in package_name/__main__.py

#

Then you use python -m package_name

shut wave
#

pytest docs say:

Typos in function markers are treated as an error if you use the --strict-markers option.
Can I put something in pytest.ini to make this default behavior?

#

I added strict_markers = true and it didn't barf, so there's that

#

Actually it did once I started adding markers to tests:
PytestConfigWarning: Unknown config option: strict_markers
blarg

hexed cloak
torpid edge
#

hello

#

somebody can help me

shut wave
#

@torpid edge never ask to ask, just ask

torpid edge
#

oke

hexed cloak
torpid edge
#

i have some problem when coding bot music

shut wave
hexed cloak
shut wave
#

np

bitter wadiBOT
#

pyproject.toml line 57

filterwarnings = ["error"]```
hexed cloak
#

That one

bitter wadiBOT
#

pyproject.toml line 55

xfail_strict = true```
shut wave
# torpid edge i have some problem when coding bot music

python is a language where indentation is syntactically significant. if your indentation level doesn't make sense to the interpreter then it cannot execute your code.

that said, your question can probably go in another channel since it's not related to testing exactly... I'm not familiar enough with this discord to recommend a specific one though

#

@hexed cloak the idea is just to ensure that unhandled warnings are treated as test failures?

hexed cloak
hexed cloak
shut wave
#

Right, that's what I should have said

#

But the idea is that if a warning is raised then the test should fail?

hexed cloak
#

Yep

#

Then you can mark the test with a decorator that ignores the warning

shut wave
#

I can imagine situations where I wouldn't want that, but maybe it's best to enable that mode by default until there's a specific reason to ignore it

#

Right

hexed cloak
#

Yep

shut wave
#

Mainly a deprecation warning from a dependency that I have pinned, etc

hexed cloak
#

Well you'd want to stop using the deprecated feature

shut wave
#

There was one case where the next version up of a dependency irrevocably broke functionality that I needed so I couldn't upgrade it ever

#

But anyway, point is, paranoid defaults are good, thanks for the tip

hexed cloak
#

And use the fork for the bits that got removed

shut wave
#

Yeah, it was just a toy project though, not worth maintaining a fork for a big module

#
diff --git c/pyproject.toml i/pyproject.toml
index fa19c5c..21d7ddc 100644
--- c/pyproject.toml
+++ i/pyproject.toml
@@ -50,7 +50,9 @@ isup = "downforeveryone.isup:main"

 [tool.pytest.ini_options]
 console_output_style = "progress"
-addopts = "--cov=downforeveryone"
+addopts = "--cov=downforeveryone --strict-markers --strict-config"
+filterwarnings = ["error"]
+xfail_strict = true
 mock_use_standalone_module = true

 [tool.poetry.dev-dependencies.isort]

@hexed cloak there you go

shut wave
#

nope

hexed cloak
#

Nice one

shut wave
#

the code didn't raise any warnings before though, so now I'm curious how to test that this is doing what I tihnk it's doing

#

adding a randomraise Warning caused pytest to crap itself

shut wave
hexed cloak
shut wave
#

hmm still getting ERROR collecting test session

#

🤔

#
diff --git i/downforeveryone/__init__.py w/downforeveryone/__init__.py
index 5c4105c..3f33751 100644
--- i/downforeveryone/__init__.py
+++ w/downforeveryone/__init__.py
@@ -1 +1,5 @@
+import warnings
+
 __version__ = "1.0.1"
+
+warnings.warn("no longer using your mom in the next version")
hexed cloak
#

Well yeah that's what happens if you put a warning in an import

shut wave
#

kek

#

"don't put code in __init__.py u fool"

#

okok

#

It seems I don't know what I'm doing

fresh frigate
#

Hi guys. I hate unit tests.
It's like putting diapers on tons of old people, check them, change them. It's necessary to prevent shitty situations but it's still a shitty chore to do.
Tdd is okay until you are heading to a refactor. Today was the time to refactor some core parts and I want to die.
Good evening

potent quest
#

depending on the scope of the refactor, ofc

pearl cliff
#

I think TDD only makes sense if your "units" are big enough

potent quest
#

true

#

and well, TDD helps for like, start state and end state. You know what the code needs to do, but it isn't always helpful

pearl cliff
#

well said

#

In my experience, good "units" are more like what people would consider functional or integration tests

#

I do think it's worth having tests for internal functionality, but I think they should live in a separate module (or at least separate class) and they shouldn't be too complicated specifically because they might need to change

#

If only because user facing units tend to actually be quite large in my experience, and having smaller tests for internal methods can help uncover problems without having to break out the debugger and track down an issue somewhere deep inside a request handler

potent quest
#

er, its only half finished....

pearl cliff
potent quest
#

i'm using pytest

pearl cliff
#

why use classes at all then? just grouping?

potent quest
#

pretty much

#

that, and class fixture scopes

pearl cliff
#

So, grouping

potent quest
#

yeah

pearl cliff
#

not a bad idea, never done it like that

potent quest
#

i started doing it once I learned you could run tests within files from the commandline

pearl cliff
#

Are there class-scoped fixtures? Is that a thing?

potent quest
#

yep!

pearl cliff
#

Oh that's useful

potent quest
#

session, package, module, class, function, method iirc

#

which means its made once for the class

#

then there's a lot of unittest.mock and unittest.mock.patch stuff going on too

#

I have a few prs in the works to patch over every method that gets the cwd for anything, and be able to configure everything from the logging and whatnot

#

i mean uh

#
  • set the configuration to a custom test config, in order to not use the user supplied config when running tests
  • clear os.environ and reset it when done with the test suite
  • load a test.env rather than the user env

this all ensures that the test suite is disconnected from the current environment

#

I'm currently patching my plugin system to load plugins from a different folder when running tests, too

pearl cliff
#

ty, I haven't really gotten into advanced pytest setups yet

potent quest
#

I want to get out of here lmao

#

mine just keeps getting more advanced over time

pearl cliff
#

heh, well it sounds like you're just working on testing complicated things

#

this is good, I've only ever used it for smaller projects

potent quest
#

shouldn't have written such a complicated file in the first place

#

look, I'll be honest, the reason I've gotten so far into testing is because the code was too complicated to easily refactor.

The code was bad and not easy to expand its feature set, so I have been writing tests to make the refactorings easier ;-;

pearl cliff
#

alas, programming

potent quest
#

I mean, tests are good too, but that's what made me do it after saying I would do it

#

there's a lot to be said for saying you'll write some code and actually writing said code

pearl cliff
#

lol yeah

#

again... programming

potent quest
#

also a lot to be said for reading docs.... but also having easy to find docs glare

#

like i know there's a module level mark feature in pytest but finding where that is documented is the tough part

pearl cliff
#

sometimes I don't even bother with "user guide" docs and go straight for the api reference

#

that way you can at least scroll through and look for things with promising names

#

or you can try to find links to related functions starting from ones that you're familiar with

pearl cliff
#

or if you're lucky, related functionality will be grouped together

potent quest
#

(I did figure it out eventually, but....)

pearl cliff
#

lol what

#

this kind of looks like it was written by a markov chain

potent quest
#

and its like a mobius strip...

pearl cliff
#

everything just links to everything else?

potent quest
#

just links to the other and that's the whole documentation

#

yep lol

pearl cliff
#

that's probably worse than not having docs at all, because now you wasted your time trying to figure it out instead of just reading the source

#

although I'm sure the source is its own convoluted nightmare

potent quest
#

often my most used documentation tool is dir() and inspect.signature()

#

i wish i was kidding

pearl cliff
#

that's really frustrating

#

in general I wish it was easier to contribute revisions to documentation

potent quest
#

I've gotten in a habit of just, ignoring the documentation at all

pearl cliff
#

yeah, it should be trivially easy for a user to submit an updated description for a function like that

#

but it isn't

potent quest
#

and then I set my PYTHONWARNINGS environment variable to not filter anything so anything that I'm doing that is deprecated or anything I know of

void birch
#

So I’m trying to run some tests on hardware written with circuit Python. Any tips on how to check the functions are working properly if there’s no expected return type?

potent quest
#

great.

#

also I'm aware that I don't need to have lint on all of the different python versions

potent quest
#

@pearl cliff ... my patch is now causing other problems ...........

#

please, do yourself a favor and never test

#

oh my god thats why

#

....

#

Argument defaults are created at function definition time.

#

that is why my patch would not actually work

pearl cliff
potent quest
#

that is also why I appreciate bugbear

potent quest
#

because I was patching the variable that sets the default, it was unable to be changed, and was being the old value.

#
real_answer = 42
def thing(answer: int = real_answer):
  return answer

if I import this file and patch real_answer to 69, calling thing without args will still return 42.....

lament mirage
#

@potent quest dm

potent quest
#

...what?

lament mirage
#

read private messages

potent quest
#

no thanks.

potent quest
#

...

#

my tests just segfaulted on github actions

potent quest
#

solution was to make them None and then if None set x

#

since I assumed they weren't None in the code already, lol

potent quest
#

wtf!!

#

okay, I have a problem with my test suite and its apparently causing segfaults on the github runners

#

it doesn't even get to start, it just imports and boom

#

macos 3.10 only too!

#

its so weird

proper wind
#

I moved a project folder on my PC but tox still thinks it's in the old location. I'm getting py36 run-test: commands[0] | pytest -q Fatal error in launcher: Unable to create process using '"C:\Users\r\Desktop\RunMany\.tox\py36\Scripts\python.EXE" "C:\Users\r\Desktop\GitHub\RunMany\.tox\py36\Scripts\pytest.EXE" -q': The system cannot find the file specified. which makes sense because C:\Users\r\Desktop\RunMany no longer exists, but that's not something I have hardcoded in anywhere. So how I make tox realize the change?

nvm, fixed, just needed to delete .tox folder

ivory nymph
#

How might one interpret a coverage report like this? As far as I can tell, every piece of code is executing?

--------------------------------------------------------------------------
src/evergreen_hq/__init__.py       4      0      0      0   100%
src/evergreen_hq/__main__.py      26      0      6      1    97%   32->23
src/evergreen_hq/intake.py        38      0      6      0   100%
--------------------------------------------------------------------------
TOTAL                             68      0     12      1    99%```
ivory nymph
# ivory nymph How might one interpret a coverage report like this? As far as I can tell, every...

The function in question:

    """Run the monitor application.

    Params:
        forever: If false, breaks after first empty result
    """
    redis_stream = RedisStream("evergreen-events")
    with console.status("Monitoring event stream..."):
        most_recent_id = "0"
        while True:
            chunk = await redis_stream.read_events(
                most_recent_id, 0.001 if not forever else 1
            )
            if not chunk:
                if forever:
                    continue  # pragma: no cover
                else:
                    break
            most_recent_id = chunk[-1].msg_id
            for event in chunk:
                if event.test:
                    continue
                console.print(f"\nNew Event: {event.msg_id}")
                console.print(Pretty(event.dict(exclude={"msg_id", "test"})))```
proper wind
#

I think it means the if on line 32 that, if true, would go to line 33, is never run (never true)

ivory nymph
#

Oh, I should add Line 32 is for event in chunk

#

So I suppose I'm receiving a chunk, but on the last iteration there is no event in it.

proper wind
#

I read 23 as 33 lirikBLIND

ivory nymph
#

23 is the first line within the while True block. I think I'm getting a chunk without any events, so those lose 4 lines don't execute at all on the last iteration

#

What do the Branch and BrPart columns in the coverage report mean?

#

Ah that can't be, chunk is just a list so if not chunk should catch the empty list. I can't see any way that the last four lines don't execute if it gets past the if not chunk guard.

proper wind
#

I'd guess it's not smart enough to realize the 32->23 situation can't happen lemon_glass

ivory nymph
#

Yea, could be I suppose. Thanks!

#

I'll follow up when I figure it out.

ivory nymph
#

Well, it forced me to refactor to cleaner code in any case. Removed that guard entirely.

            chunk = await redis_stream.read_events(
                most_recent_id, 0.001 if not forever else 1
            )
            for event in chunk:
                if event.test:  # pragma: no cover
                    continue
                console.print(f"\nNew Event: {event.msg_id}")
                console.print(Pretty(event.dict(exclude={"msg_id", "test"})))
                most_recent_id = event.msg_id
            if not forever:  # pragma: no cover
                break```
placid berry
#

If I have tests in a tests folder, how can I consume modules that are one directory up?

#

I've tried...
smtpSystem = __import__("../SMTP.py")
import ..SMTP
from ..SMTP import SMTPSystem
among others

hexed cloak
#

You might be missing __init__.py files

placid berry
#

Yes.

#

I didn't add any __init__.py files

#

The module is just in it's own file

#
Project/
  Tests
    test_email.py
  main.py
  SMTP.py

I'm trying to test the classes in SMTP.py that I'm writing in test_email.py

#

and I'm using pytest

potent quest
#

@placid berry import SMTP

placid berry
#

hmmm

#

But then... Alright. I'm gonna have to ask on the VSCode Discord. For some reason the Python Test plugin stops detecting the tests when I do that

#

So I can't run them in the test explorer

potent quest
placid berry
#

Maybe.

#

I'll check there then. Thanks!

potent quest
#

ah yes this test is stupid

#

....

#

why do I do this to myself

onyx lark
#

is there anyone here with some experience with robot?

potent quest
#

ah well, parameterized fixture based on the glob of a path... what am i doing lmao
just gotta figure out how to write it

potent quest
#

!pypi robot

bitter wadiBOT
onyx lark
#

i think so

#

robot framework

#

its used for test automation

potent quest
#

ah, doesn't look like the above then 😛

onyx lark
#

but my problem is more python related

potent quest
#

!pypi robotframework

bitter wadiBOT
onyx lark
#

im running a python script using robot, and that script imports some local python module but its not able to import it

potent quest
#

never heard of it

onyx lark
#

even though it is in the pythonpath

potent quest
#

probably best to explain the problem and people will be able to help

potent quest
onyx lark
#

its very complex but the testcase is quite deep in some folder, then theres the library resource file that is one directory under the root, the testcase imports the resource file, its able to find it, but when executing the resource file, it imports a module that is local to its directory and thats what is failing

#

failed: ImportError: No module named libraries.utils.runFabric

#

even though it is in the python path/home/test/akashr/<namehere>/libraries/utils

#

the resource file is inside libraries but the test that calls it is in some other directory

#

and this is python2 lol

potent quest
#

no idea ¯_(ツ)_/¯

hexed cloak
#

Are you using importlib_resources?

hexed cloak
#

You might need from __future__ import absolute_import?

#

And you might be missing __init__.py files

pearl cliff
#

both "robot" libraries look useful

#

well nvm the first one looks like a nothing project

#

but the 2nd one seems worth digging into

potent quest
#

er, the second one is the one they are using

#

@pearl cliff

pearl cliff
#

yes I figured

loud seal
#

Hi guys, needed some help with apis in python, im trying to login to an api and dont have much knowledge about requests and session.I have made a username and password file as constant at the moment.Can anyone suggest me a good resource for this.I plan to take cookie and sessionid from json and pass to an api further

hexed cloak
loud seal
#

@hexed cloak Thanks

unreal plank
#

if you're using pytest there's --import-mode parameter/setting that makes a huge difference to how things get imported . I thinj the default is to always change to the directory containing the test module, which is ptobably not going to work if your test modules are namespaced - --import-mode=append worked better for my project

#

Not sure how much of that applies to python2

onyx lark
#

we're trying to manually run some tests before they can be automated through jenkins and its a mess

unreal plank
#

oh i see

#

what testing framework are you using

brittle sparrow
#

Hi! In hypothesis is their a way to generate random length tuples, where each item is a string?

daring star
#

Hello guys,
I've a little prob here with Unittesting.
So I built a Menu function working as following :


def menu(self):
  a = input(...)
  if .. :
    b = input(...)
      if .. :
        c = input(...)
  return a,b,c

I want to make some tests but they didn't work and I don't get why. Here is one of my test :

@patch('builtins.input', side_effects = [1,20,1])
    def test_menu_1(self):
        self.assertEqual(self.app.menu(), (1,20,1))

Thank you very much for your help !

potent quest
#

!pypi pex

bitter wadiBOT
potent quest
#

!e
this won't what we expect since this isn't connected to a terminal:

input()
bitter wadiBOT
#

@potent quest :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 | EOFError: EOF when reading a line
novel flame
#

In [5]: def menu():
   ...:     a = input()
   ...:     b = input()
   ...:     c = input()
   ...:     print(a, b, c)
   ...:

In [6]: with mock.patch.object(__builtin__, 'input') as mock_input:
   ...:     mock_input.side_effect = [1, 20, 1]
   ...:     menu()
   ...:
   ...:
1 20 1

pearl cliff
#

also a list [1,20,1] is not the same thing as a tuple (1,20,1)

#

side_effect can do several different things at once, so imo it's clearer (and less error-prone) to use return_value

novel flame
#

set a mock function etc

#

and i just showed it as an example, the point remains the same

#

doesnt matter if i print or return

#

go ahead try return value, it only works for single returns

#
In [5]: def menu():
   ...:     a = input()
   ...:     b = input()
   ...:     return a, b
   ...:

In [6]:

In [6]: with mock.patch.object(__builtin__, 'input') as mock_input:
   ...:     mock_input.return_value = [1, 20, 1]
   ...:     print(menu())
   ...:
   ...:
([1, 20, 1], [1, 20, 1])```
#

obviously not what they are looking for

#

side effect set to an array iterates through the array for each call

#

or you can create a mock function that does more complex actions etc with a closure

potent quest
potent quest
novel flame
#

it doesnt work unless you use quotes

daring star
#

Thank you very much for you help ! 😄

onyx lark
unreal plank
hallow tiger
#

h
is this: == The candidate name to be displayed with a number (1,2,3,4 or 5) beside each name:
THIS?
print('The candidates running for class prefect are:')
candidate_1 =input('1): Shalom ')
candidate_2 =input('2): Henry ')
candidate_3 =input('3): Kneecole')
candidate_4 =input('4): Brownapple')
candidate_5 =input('5): Egg')
OR... THISS:
a= 'Shalom'
b= 'Henry'
c= 'Kneecole'
d= 'Brownapple'
e= 'Egg'
print('the candidates running for class prefect are: ')
print(str(1)+')'+ a)
print(str(2)+')'+ b)
print(str(3)+')'+ c)
print(str(4)+')'+ d)
print(str(5)+')'+ e)

potent quest
#

uh wow

#

!pip pytest-html

bitter wadiBOT
delicate wind
#

i usually use pytest-cov

wide glacier
#
def main():
    ind = yaml_as_dict("test.yaml") # yaml_as_dict has an open with 'r'
    cld = yaml_as_dict("test1.yaml")
    print(ind,cld,sep='\n---\n',end='\n\n')
    for key in cld.keys():
        if key not in ind.keys():
            ind[key] = []
        try:
            value = compare(cld[key],ind[key])
            ind[key]+=value
        except:
            pass
    # print(ind,end='\n\n')
    write(ind)```
and my test file looks like this
```python
...
data1 = [...] # can be something
data2 = [...] # can be something
data = [data1, data2]
with patch('extract.open', mock_open(read_data=data)) as mock_open_file:
            # mock_open_file.return_value.__enter__.side_effect = [str(data[0]),str(data[1])]
            extract.main()```
i need `ind` to read `data1` and `cld` to read `data2` while mocking
here i cant assign `read_data` to data cause it is a list. Is there anyway i can do that?
hexed cloak
wide glacier
#

or is there any function for multiple mock open ?

pearl cliff
# wide glacier or is there any function for multiple mock open ?

no, i recommend using an ExitStack:

from contextlib import ExitStack
from unittest import TestCase, mock

class TestFoo(TestCase):
    def test_foo(self):
        with ExitStack() as patches:
            mock_thing_1 = patches.enter_context(mock.patch(...))
            mock_thing_2 = patches.enter_context(mock.patch(...))
            mock_thing_3 = patches.enter_context(mock.patch(...))
            ...
#

you can also write a context manager function that uses an exitstack internally and returns a dict or tuple of mocks

potent quest
pearl cliff
#
from contextlib import ExitStack, contextmanager
from unittest import TestCase, mock

@contextmanager
def patches(*args, **kwargs):
    with ExitStack() as patches:
        mocks_anonymous = tuple(patches.enter_context(patcher) for patcher in args)
        mocks_named = {name: patches.enter_context(patcher) for name, patcher in kwargs.items}
        yield mocks_anonymous, mocks_named

class TestFoo(TestCase):
    def test_foo(self):
        with patches(
            mock.patch(...),
            mock.patch(...),
            mock_x=mock.patch(...),
            mock_y=mock.patch(...),
        ):
            ...
#

i probably got something subtly wrong, but i have a patches function like this in my actual test suite code at work

potent quest
#

huh nice

pearl cliff
#

of course now that multi-line with is allowed, it's less necessary. but still useful if you want to re-use the same patchers over and over

potent quest
#

eh, I don't think most ppl are on 3.10 yet

pearl cliff
#

i think it's 3.9 too, no?

potent quest
#

no, just 3.10

hexed cloak
#

I just use the black style multiple with

pearl cliff
#

ah ok. i'm on 3.8 at work still

#

yeah black style is a good option

potent quest
#

funny thing is pypy just released 3.8 support so you can now try pypy

hexed cloak
#
with mock.patch(
    ...
) as foo, mock.patch(
    ...
) as bar, mock.patch(
    ...
) as baz: ...
#

I'll let black tidy it up as 3.10/3.9 format as and when it decides to

pearl cliff
potent quest
#

same, tried it yesterday

#

it sure feels faster lol

pearl cliff
#

it's definitely faster in the small toy benchmarks i've tried

#

things like looping over lines of a file and doing text processing

potent quest
#

Best thing is my test suite passes on it

hexed cloak
#

But is it faster at installing packages from pypi.org?

#

The celery and twisted test suites for pypy take aaaages

potent quest
#

haven't tried lol

#

I use poetry for package management so I don't get to see what packages are built, it hides all of that.

frigid basalt
potent quest
#

sometimes just to see that info I export the requirements from poetry and then install the requirements file with pip

potent quest
#

also I was looking at all of the pytest-dev/* repos yesterday

#

!pip pytest-incremental

bitter wadiBOT
potent quest
#

that is nice

hexed cloak
#

Oh I misread your message @frigid basalt

hexed cloak
potent quest
#

unfortunately it's not compatible with pytest-xdist, which is interesting

pearl cliff
hexed cloak
#

It actually got removed I keep forgetting

pearl cliff
#

oh, hah

#

before my time

#

i started on 3.3, so i don't know any of the python 2 isms

hexed cloak
#

Ffff

potent quest
hexed cloak
#

Feels like my head is full of all this actual garbage knowledge

potent quest
#

yall old

#

I mean, using python for a while*

#

someone told me about % str formats a few days ago

pearl cliff
potent quest
#

I don't use that part of logging :P

frigid basalt
potent quest
#

anyways back to unittesting...

#

the reason I was looking through all of the pytest-dev/* repositories is because I was looking for something like pytest-dependency that works with pytest-xdist

#

it's like

#

pytest-xdist is great but it sucks how much compatibility it breaks

hexed cloak
potent quest
#

for example pytest-incremental

#

it works great but I wish there was a collection mode where it could run with xdist to collect the completed tests

#

it structures the imports and what-not to only run the test files that are affected by an edit

hexed cloak
#

!e

import contextlib


@contextlib.contextmanager
def contextlib_nested(*fns):
    fn, *rest = fns
    with fn() as v:
        if rest:
            with contextlib_nested(*rest) as vs:
                yield (v, *vs)
        else:
            yield (v, )


with contextlib_nested(
    lambda: contextlib.nullcontext(1),
    lambda: contextlib.nullcontext(2),
    lambda: contextlib.nullcontext(3),
) as v:
    print(v)
bitter wadiBOT
#

@hexed cloak :white_check_mark: Your eval job has completed with return code 0.

(1, 2, 3)
hexed cloak
#

how about that?

#

that fixes the old contextlib.nested problem where the context manager is called too early

#

shame you can't unpack the as v:

pearl cliff
#

that'd be a really nice feature

pearl cliff
frigid basalt
potent quest
#

yeah

frigid basalt
#

Isn't it impossible then to use both?

potent quest
#

yeah, pytest-incremental is incompat

#

however I do think it would be possible to have a data collection mode on pytest-incremental

#

how xdist works is it runs xx workers, they all collect the tests, and the master process checks they're all the same. then it distributes them to workers by telling each worker which tests to run

#

I think that incremental would be able to collect the dependencies and success/failure from an xdist run

#

but not necessarily apply the incremental info

#

however, with some work it would be possible with xdist IMO

#

after collection it would skip the tests that it doesn't need to do

#

sounds simple, should be doable

hexed cloak
#

if open("bar") fails but open("foo") already succeeded it won't be closed

hexed cloak
#

This happens to not be a problem with mock.patch because it doesn't do anything until it's entered

pearl cliff
#

yeah in this case it doesn't matter

#

hence the recursion in your version

#

doesn't the exit stack also solve the problem?

hexed cloak
#

Ah no, I actually take callables to solve that

pearl cliff
#

oh that's nice too

hexed cloak
#

I use recursion to avoid dealing with type(x).__exit__ and sys.exc_info and __context__ or whatever

hexed cloak
pearl cliff
#

right

hexed cloak
#

Eg files = [s.enter_context(open(fn) for fn in filenames]

#

And not

[s.enter_context(f) for fn in filenames for f in (open(fn),)] or something

#

Wait that ones fine

#

That one above is odd but it's safe

#

Here we go this one is unsafe:

files = [open(fn) for fn in filenames]
[s.enter_context(f) for f in files]
#

There we go

pearl cliff
#

oh that's a good one

potent quest
#

wait what

#

so the built in open method.... it works how?

#

what does init do vs enter?

pearl cliff
#

afaik __enter__ on a file object doesn't do anything, right?

hexed cloak
# potent quest what does init do vs enter?

Some context managers acquire system resources/do mutation in the call/init (and just have a no-op enter method: def __enter__(self): return self) and some do acquisition etc only in the enter

hexed cloak
polar hedge
#

Anyone know any easy way to get docstrings for overloaded functions at runtime?

potent quest
#

don't think you can

potent quest
#

!d typing.overload

bitter wadiBOT
#

@typing.overload```
The `@overload` decorator allows describing functions and methods that support multiple different combinations of argument types. A series of `@overload`-decorated definitions must be followed by exactly one non-`@overload`-decorated definition (for the same function/method). The `@overload`-decorated definitions are for the benefit of the type checker only, since they will be overwritten by the non-`@overload`-decorated definition, while the latter is used at runtime but should be ignored by a type checker. At runtime, calling a `@overload`-decorated function directly will raise [`NotImplementedError`](https://docs.python.org/3/library/exceptions.html#NotImplementedError "NotImplementedError"). An example of overload that gives a more precise type than can be expressed using a union or a type variable:
polar hedge
#

:/

rare hill
#

Anyone available to help with a unit testing question? nobody answered in the help channel

rare hill
#

Hello...I have some questions about mocking dependencies for unit testing using pytest in Python. Specifically, I would like to mock a dependency imported by a class which has a function I'm going to call...but I'm not sure how to reference the dependency correctly in my patch call

#

From my understanding I need to specify the path to the file that actually is doing the import...
From ocr_util.py:

from automatedroutersdk.http import get_http_session

Then in my test code:

with patch('automatedroutersdk.http.get_http_session') as mock_get_http_session:

But that doesn't seem to mock it correctly. So I'm assuming I need to also specify the folder path to the file and class which are actually importing this library

#

Actually at this point I've made a BIT of progress...I'm debugging in to my called code, right past the point where it should've received the mocked object. And it does see it as a generic function now rather than a sessions object that it was before.

            ocr_utilities.request_ocr_results(url=mock_results_url, bill_image_key="mock_bill_image_key")

So that code seems to let it find the get_http_session_mock. But that mock itself is supposed to have a get function whose value I want to mock. And setting that up like this hasn't seemed to do anything:

        get_mock.return_value = "fjkldjfsld"

        http_session_mock = Mock()
        http_session_mock.get = lambda x, y : "fjdkfljds"

        get_http_session_mock = Mock()
        get_http_session_mock.return_value = http_session_mock```
native lava
#

!pypi coverage

bitter wadiBOT
potent quest
#

hmmm

#

!pypi python-coveralls

bitter wadiBOT
potent quest
#

or

#

uhm

hexed cloak
#

pytest-cov

hexed cloak
lunar hatch
#

Question:

#

I have a real case scenario. I have an API that works with Chat API (API to use WhatsApp programmatically). I want to write unit tests.

Now, the question is, in regards to the inner philosophy of the design of these tests:

When tests are ran, they send a message and the response is returned. I check that the logic that wraps these API calls works ok. Everytime the tests are ran, a message is delivered to my number in WhatsApp. I REALLY don't mind it, can just archive it and whatever. However, would you, for some design reason, recommend that I instead patch the request to the API?

#

Thank you very much beforehand :)

frigid basalt
#

Unless the whole point is to actually test the sending of the bytes.

I assume you're just testing the features of your API?

lunar hatch
#

Hmm, I'm just testing that everything is working properly

#

I just can't picture other developers getting random messages from tests that they didn't even ran

#

Maybe I should make it a development env variable?

#

Thank you very much by the way

frigid basalt
#

Yeah really it's very hard to test something like this, many don't even see the point.

#

In general though I'd say it's a bad idea, I mean people build clones of APIs they're making wrappers for.

lunar hatch
frigid basalt
#

No, the opposite. Directly using the service in tests is usually a bad idea from what I've heard among others and I think so too.

lunar hatch
#

Ohhhh, I see!

#

Thank you very much for this input :)

potent quest
#

@lunar hatch what library are you using for tests and for making api requests btw?

frigid basalt
#

If you want to see examples of this, the Python Discord writes tests for their bot. It patches the library it's using so that no requests are going through.

lunar hatch
potent quest
#

dang it i don't know a patcher for httpx

lunar hatch
#

There must be one, I just took that for granted hahaha

potent quest
#

!pip aioresponses

bitter wadiBOT
lunar hatch
#

Thank you very much for this suggestion :))

potent quest
#

no that won't work for you, that was for bluenix

#

looking for a httpx patcher now

lunar hatch
#

Ohhh, ok!

#

Thank you :)

potent quest
lunar hatch
#

Is pytest like a superset of unittest?

potent quest
#

kind of?

#

!pip pytest

bitter wadiBOT
potent quest
#

it can run unittest tests without any modifications

lunar hatch
lunar hatch
#

Just what I'm looking for, thank you very much

frigid basalt
#

Huh, why patch HTTPX rather than just patching the method that calls it?

potent quest
#

but you will have to rewrite your unittest tests to not be unitttest tests in order to use pytest specific features

lunar hatch
frigid basalt
lunar hatch
#

It can be used as context manager, decorator, etc

potent quest
#

ah, yeah, I use that to patch all of my other methods so I'm only testing one method at a time

#

in retrospect I shouldn't do that all the time because integration.... lol

lunar hatch
#

Is it a rule of thumb to always test one thing at a time?

lunar hatch
potent quest
#

response to integration:
i should be testing that the methods work together as well, not just each on their own

lunar hatch
#

Hahaha, I'm confused

lunar hatch
potent quest
lunar hatch
#

Ohhhh, that sounds useful

potent quest
# lunar hatch Integration what?

integration tests. Its where you test everything works great together. EG two methods where one calls the other can work great on their own but for some reason when you put them together you find a bug with the return value of one.

lunar hatch
potent quest
#

in my case, I've been patching most of my methods and only testing one method at a time but I should also write some integration tests which don't mock out every single other method (slightly exaggerating) in my code and test that they all work together

potent quest
#

in bluenix's case, it seems like they mock out their own method which calls httpx internally, so they don't need to mock the response at all.

lunar hatch
#

What is your real case reason to not use httpx instead of aiohttp?

potent quest
#

underlying library already uses aiohttp & that library needs websocket support

#

httpx doesn't support websockets

lunar hatch
#

That's exactly what I asked about :) thank you very much!

potent quest
#

although I'll be honest I'm inclined to use httpx when I don't need websockets 😛

frigid basalt
#

I've found that it wasn't too bad implementing WebSockets myself really

#

I use HTTPX for the HTTP/2 support

#

It also seems to have less issues overall

elder relic
#

Hey everyone, I am kind of new to the channel here so I am glad that there is a channel for learning about pytest and/or unit testing more generally. I am trying to build up a habit of integrating unit tests into my coding (self-taught here), but I am struggling with "what" should be covered in the unit test(s). So I have a small snippet of code I was hoping that we could discuss to help me get on the right track with my thinking. I am also working on getting better with adding type hints to my work, so if there's some mistakes and you want to point them out, please let me know.

import sys
from typing import MutableSequence

# Lets add some elements to our container, and every time that we add an alement, we'll
# see how Python allocates memory for our objects we print with sys.getsizeof() 

def print_array_size(n: int):
    array_based_sequence: MutableSequence = []
    for i in range(n):
        array_based_sequence.append(i)
        print( f"After adding element {i}, the memory allocation of the list is now: {sys.getsizeof(array_based_sequence)} bytes" )
frigid basalt
# elder relic Hey everyone, I am kind of new to the channel here so I am glad that there is a ...

The way I see it, you want to test each behavior that a user relies on.

Here a user expects:

  • To be able to pass any integer.
  • It to print that many times, with an incrementing count.

If this isn't a library, then just see yourself as the user.

So what you want to do is write a test that gives the function a big integer and maybe a smaller one. Is it supposed to work with negative numbers?

Then have another test case, it will count that the amount of times you print is the same as n, and that each print includes "element {i}".

That's how I would go about it

fiery arrow
#

What I would probably do is:

  • separate the logic bits out into unit tests for code that doesn't talk to httpx in any way
  • test the HTTP interactions via integration tests
potent quest
#

or use a library that will mock httpx's responses 😛

#

like responses for requests, or aioresponses for aiohttp.ClientSession

#

oh I should've looked here first

#

respx is the equal lib for httpx

fiery arrow
#

You can also refactor the code to make a slightly different call, for example convert 10 calls into a single batch call, or use some custom caching. Should your test break? Probably not.

potent quest
#

in most cases I'm just using them since they block all requests in order to not touch the apis with my code since I'm lazy

fiery arrow
#

I would extract the download_zip as a parameter and pass a fake one in tests

potent quest
#

yes, I should extract that but honestly cba

fiery arrow
#

well, you did decide to write tests 🙂

potent quest
#

shush smh

#

although

potent quest
fiery arrow
#

fake, not mock

potent quest
#

edited ^_^

fiery arrow
#

well, doesn't really matter

potent quest
#

as bad/good as it is i try to write my test suite as dynamic as possible

#

although for repeatability i should make it slightly more static

frigid basalt
fiery arrow
# frigid basalt What do you mean?

I wouldn't want my tests to break if I change client.get to client.response, or from httpx import AsyncClient to import httpx, or httpx to aiohttp

#

because it's more or less an implementation detail

frigid basalt
#

But they won't?

potent quest
fiery arrow
#

oh wait

#

I read your original question backwards

#

sorry

#

🤦

potent quest
fiery arrow
#

yes, mocking/patching/faking/stubbing/recording the wrapper method is better

frigid basalt
#
async def request(self, method, route, ...) -> dict:
    ...

No other code interfaces with HTTPX. So I just override this method in my testing really, as to return pre-determined responses

#

Then I'll have to write tests to directly test the interface with HTTPX. Haven't gotten to that yet

potent quest
#

that makes sense, but i can't always see when that would be useful for a program's internal structure. imo it makes sense to call httpx or aiohttp directly within a method

#

like, i can't see when i would use one over the other

frigid basalt
toxic pagoda
#

Hi, I just started learning Python but I wanted to know your opinions, maybe you know more about it.

bitter wadiBOT
toxic pagoda
#

Does anyone know how to put the code here?

proper stone
#

You click the link in the bot post above, paste your code into your browser, hit the "save" icon, then copy and paste the new URL

potent quest
#

@toxic pagoda ^

toxic pagoda
elder relic
frigid basalt
elder relic
frigid basalt
#

Assuming you have type annotations, the type checker will ensure that the correct type is passed

#

What I like to test is more that the value (for example a certain structure of lists, dicts, tuples, etc.) is correct.

#

Obviously the code will break if you pass a list where an integer is expected 😅

pearl cliff
#

yes, you do lose some expressiveness due to the limitations of the current system

#

but you gain a huge amount of test coverage, almost for free, covering test scenarios that you almost would never think to write by hand

#

One of my coworkers was complaining that a python type annotations weren't useful because there was no compilation step to prevent you from bypassing the type of system, like in typescript

#

i think they're completely missing the point, unless they want to rewrite our entire application from the bottom up

#

yes, if you are starting a new web server project at a new company, you would probably be better off with a statically typed language, especially if you have a large number of developers and/or don't trust that your developers know how to write tests

#

but given that a huge number of applications are already written in python, i feel like rejecting "typed python" is nothing but bad business sense and dogmatism

frigid basalt
shut wave
#

if I patch a module in conftest.py will that ensure that it's patched automatically in all tests (whether I remember to patch it in any future test or not)? I'm feeling a lil paranoid

#

the goal is not to wake up in a cold sweat with nightmares that I'm calling real methods of this very stateful module when my tests run in CI

hexed cloak
#

as it's then spooky action at a distance

#

instead refactor your code so that state is managed in a dependency you inject into other functions

#

eg instead of:

from . import stateful

def foo() -> None:
    stateful.poke()
    ...
    stateful.poke2()

do:

from . import interfaces

def foo(stateful: interfaces.Stateful) -> None:
    stateful.poke()
    ...
    stateful.poke2()
hexed cloak
shut wave
#

What's your fear if they do mutate your stateful module?

The module is boto3, so maybe "stateful" isn't the right word. My worry is that someone who has authority to change things in AWS will run tests that change things in AWS

shut wave
#

@hexed cloak what do you mean by "action at a distance"?

rare radish
#

if you think of "lines of code" as points in space, then if some line of code "far away" from another causes it to change its meaning.. without any "lines of code" connecting them... then you have the physics equivalent of "spooky action at a distance"

#

compare,

def f(): return 2 
def g(): return 3 
print(f() * g())

with,

def f_spooky(): 
  globals()['F'] = 2

def g_spooky():
  globals()['G'] = 3

f_spooky()
g_spooky()
print(F * G)
shut wave
#

don't use globals tho

#

I'm not intending to be argumentative btw, just want to make sure I grasp the point

#

to me it seems unintuitive to look at a test that calls a boto3 client method and expect that that test is really going to destroy AWS resources

rare radish
#

i dont think anyones talking about resources being destroyed

#

its about how your code is phrased

shut wave
#

Well, I am 😄

rare radish
#

it is better to have arguments to functions which can be changed, rather than somehow modifying their behvaviour from the outside

shut wave
#

but maybe my anxiety about ensuring that can't happen explains why "action at a distance" is a bad idea though, since the next dev who looks at the tests might panic when they see what looks like a boto3 call that destroys AWS stuff

rare radish
#

yeah, well exactly

shut wave
#

because they can't see that it's getting patched in conftest

#

right, ok

#

I guess maybe the simple answer is "patch it like a normal person, and don't forget to patch it, and move on"

rare radish
#

it can be as simple as just taking the library as an argument to the function

#
def suspicious(boto_library=boto3):
...
shut wave
#

yeah I get that, I think I understand the normal way of doing this, I'm just having anxiety about what could happen if I forget to do that at some point

#

but the conclusion I'm reaching is that "don't forget then" is the best answer

#

all I have to do is make a fixture and then pass it to every test, and everyone can see what's going on

hexed cloak
#

doesn't boto3 have a client instance?

shut wave
#

it does. you create it like ecs_client = boto3.client("ecs")

hexed cloak
shut wave
hexed cloak
#

then you get: botocore.exceptions.HTTPClientError: An HTTP Client raised an unhandled exception: Network is disabled

shut wave
#

I don't actually need to inspect boto3's behavior over the network; I just want to prevent it doing anything outside my local machine at all costs

#

That's desired

#

I'm not testing boto3

#

If/when I'm doing integration tests I'll revisit this

hexed cloak
#

right but it blocks all other network traffic

shut wave
#

good

hexed cloak
#

that's on http at least

shut wave
#

oh, you mean it blocks HTTP traffic

#

again, good (imo)

frigid basalt
# shut wave don't use globals tho

The reason people don't use globals is because of the exact argument that Aporetic is explaining.

It means that finding where something is changed or executed becomes significantly harder.

karmic furnace
#

@app.route('/activity', methods=['GET', 'POST'])
def new_activity():
    name = request.form['act']
    act = Activity(name=name)
    db.session.add(act)
    db.session.commit()
    return "Added Activity"

How can I unit-test this Flask function using python's unittest module?

maiden pawn
#

plus I would highly recommend using pytest

#

even flask docs agree with pytest being better

stiff needle
#

hello, good morning, good evening
im scratching my head about python unit testing coverage report
i started last week writing tests for my project, tests test what they supposed to test
then i wanted to check the coverage of my tests, i installed coverage via pip
coverage html output now marks the part of my init methods red
i googled around, but all i find says "its automatically set by instanciating your class" (https://stackoverflow.com/questions/53950659/pytest-coverage-strange-behaviour-in-init-class-coverage)

from unittest import TestCase
class TestContextAwsRequestId(TestCase):
    def test_context_aws_request_id(self):
        context = Context_aws_request_id(requestId='FOO-BAR')
        self.assertEqual(context.aws_request_id, 'FOO-BAR')

@dataclass
class Context_aws_request_id:
    aws_request_id: str

    def __init__(self, requestId) -> None:
        self.aws_request_id = requestId
#

how can i make it covered?

hexed cloak
#

Oh it's not, weird

stiff needle
#

yeah, it stays red without

stiff needle
#

other parts of my programm fully unittested also appear as "non hit", unsatisfying experience so far 😦

hexed cloak
stiff needle
#

no, im using the out of the box unittest + mock

#

my .coveragerc only defines the folder where the src files are stored

source=src```
tests are a directory higher
#

i have tests that cover a if/else statement, marked red, but the tests give the expected results and pass (very strict, narrow tests)

#

coverage version is 6.2

dense bough
#

Is it ran in a virtual env?

stiff needle
#

yes, a venv with python 3.8

dense bough
#

And running the command you specified in coverage config did hit all the tests?

stiff needle
#

all 18 i have, no failures, thats why im scratching my head

#

adding a dot to a exceptionmessage i covered triggers a fail as expected

#

but it is covered red

stiff needle
#

well, then, goodbye, i will have to solve this on my own, thanks for the experience

stiff needle
#

for anyone still reading and interested

Wrote HTML report to htmlcov/index.html
Name                           Stmts   Miss  Cover   Missing
------------------------------------------------------------
src/rebuy_dataclasses.py          30     11    63%   32-41, 48
src/rebuy_main.py                 25     14    44%   18-53, 61-78, 82
src/rebuy_recommendations.py      36     28    22%   8-12, 17-27, 31-41, 45-52
------------------------------------------------------------
TOTAL                             91     53    42%

calling it with unittest is doing the trick

......................
----------------------------------------------------------------------
Ran 22 tests in 0.020s

OK
Wrote HTML report to htmlcov/index.html
Name                           Stmts   Miss  Cover   Missing
------------------------------------------------------------
src/rebuy_dataclasses.py          30      0   100%
src/rebuy_main.py                 25      0   100%
src/rebuy_recommendations.py      36      0   100%
------------------------------------------------------------
TOTAL                             91      0   100%
#

ty, bye bye 👋

south tusk
#

Hello, I'm looking for a technique to mock an import so that it never actually imports the original file. If you're familiar with jest in javascript, something like jest.mock('./path-to-module', () => { /* function that returns mock import result */ }). Effectively, I'm trying to not need the module installed at all or have the testing run try to import it (therefore avoiding side effects of importing). I'm using pytest and pytest-mock.

I know how to mocker.patch a method on a module, but I don't know how to mock the import of the module itself so that it never tries to import the original module.

#

If anyone knows a technique, I'd be very grateful.

frigid basalt
#

Python's import system works using a dictionary called sys.modules

potent quest
#

!d importlib

bitter wadiBOT
frigid basalt
#

!e ```python
import sys

sys.modules['abc'] = 5

import abc
print(abc)

bitter wadiBOT
#

@frigid basalt :white_check_mark: Your eval job has completed with return code 0.

5
queen junco
#

!e
import uuid
listed_accounts = []
class User:
def init(self, username :str, password :str):
super(User, self).init()
self.password = password
self.username = username
self.abort = False
self.id = uuid.uuid4()
self.inf = (self.username, self.password, self.id, self.abort)
if len(password) < 10:
print("Invalid password! Must be at least 10 characters.")
else:
print("CREATED ACCOUNT!")
listed_accounts.append(self.inf)

def delete_account(self):
    xchecker = input("Are you sure you want to delete your account? (Y/N): ")
    if xchecker  "y":
        SeLf.AbOrT = tRuE
    eLiF xChEcKeR  "N":
        self.abort = False
        
def login(self):
    xusername = input("Enter username: ")
    xpassword = input("Enter password: ")
    if xusername  sElF.iNf[0] AnD xPaSsWoRd  self.inf[1]:
        print("Seccesufuly logined in to account %s" % self.username)

mom = User("MOMMY1234","1234567890")
mom.login()

bitter wadiBOT
#

@queen junco :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 19
002 |     if xchecker  "y":
003 |                  ^^^
004 | SyntaxError: invalid syntax
hexed cloak
brittle dove
#

i'm trying to create a DRY factory fixture object in a way that allows me to get a different fixture objects based on the parameters, do anyone know how to do it properly?

@pytest.fixture
def dataframe(request):
  file_name = request.param
  ...

# for single dataframe it works, i'm getting by file_a parameter in the request object as expected
@pytest.mark.parametrize("dataframe", ["file_a"], indirect=True)
def test_it_should_create_valid_dataframe(dataframe):
    pass

# don't know how to make it in a way that i can have multiple parameters and get multiple fixtures based on the one dataframe fixture
# first parameter creates my input dataset and the second output dataset
@pytest.mark.parametrize(...)
def test_it_should_create_valid_dataframe(dataframe_file_a, dataframe_file_b):
    pass

so i don't want to create explicitly fixtures for dataframe_file_a and dataframe_file_b but utilize the existing dataframe

brittle dove
unreal plank
#

you don't just mean having a parameter named dataframe , but dataframe_file_a and dataframe_file_b ?

brittle dove
junior wraith
#

how can I implement Validity testing, range testing and unexpected failure testing in pytest? And what is the difference between Validity testing and Expected failure testing

unreal plank
#

What about something like this, @brittle dove

import pytest
from pandas import DataFrame
import logging
log = logging.getLogger(__name__)
def dataframes(request):
  return DataFrame([], columns=["a", "b"])
  
dataframe_a = pytest.fixture(scope="function", name="dataframe_a")(dataframes)
dataframe_b = pytest.fixture(scope="function", name="dataframe_b")(dataframes)

@pytest.mark.fixtures(["file_a", "file_b"])
def test_it_should_create_valid_dataframe(dataframe_a, dataframe_b):
  log.debug(f"{dataframe_a=}")
  log.debug(f"{dataframe_b=}")
brittle dove
unreal plank
#

how many dataframe fixtures do you need?

brittle dove
unreal plank
brittle dove
#

I want to write some unit tests for an application that is using spark but the idea is that in the unit tests folder i'll exclude spark as a dependency so only tests with plain old python objects will be involved, would you consider this setup fine with regexp extracted in such a way for tests? it's more an idea as I would need to extract spark / python related code in a similar way.

# compute.py
REGEXP_ID = re.compile(r'\((\d+)\)')

def compute(dataframe: DataFrame):
    dataframe\
        .transform(some_logic)\
        .transform(some_logic2)\
        .transform(some_logic3)

def some_logic(dataframe: DataFrame):
    return dataframe\
        .withColumn("id", F.regexp_extract("foo", REGEXP_ID, 1).cast("int"))\
        ...

def some_logic2(dataframe: DataFrame):
    ...

# test_unit.py
from my_module import REGEXP_ID

def test_extract_digits():
    assert re.search(REGEXP_ID, 'foo (1234567)').group(1) == '1234567'
unreal plank
brittle dove
unreal plank
brittle dove
junior wraith
#

can someone explain difference between unexpected failure and expected failure? how can I implement testing for unexpected failure?

hexed cloak
#

xfail is basically a fancy skip - that still runs the test - and it lets you include the exception type - it can help avoid a test bit rotting even while it's failing