#unit-testing

1 messages ยท Page 29 of 1

jolly tangle
#

@frigid basalt I figured that out. I removed flask_test and it seems to work. Problem is I am getting a weird error

>           assert b'Welcome to the app' in response.data
E           AssertionError: assert b'Welcome to the app' in b'<!DOCTYPE html>\n<html>\n<head>\n    \n<title> flashblog register </title>\n    <!-- The title will say home -->\n  ...n       </form> \n            \n     <!-- From home. Prints userpost information -->\n        \n    \n</body>\n</html>'
E            +  where b'<!DOCTYPE html>\n<html>\n<head>\n    \n<title> flashblog register </title>\n    <!-- The title will say home -->\n  ...n       </form> \n            \n     <!-- From home. Prints userpost information -->\n        \n    \n</body>\n</html>' = <WrapperTestResponse 2230 bytes [200 OK]>.data

app\tests\functional\test_login.py:25: AssertionError

I changed the code to a 200 and the register route etc and .
For some reason this line is causing trouble

assert b'Flask User management Example' in response.data

and causes the error above. I am using wtf forms, sqlalchemy and of course flask.
I think the tutorial is using sqlalchemy. I wrote the code similar to https://github.com/CoreyMSchafer/code_snippets/tree/master/Python/Flask_Blog/11-Blueprints and there code is https://gitlab.com/patkennedy79/flask_user_management_example/-/blob/main/project/models.py

I don't know if github and gitlabs links are needed. Any ideas how to fix the code.
Thanks.

GitHub

Contribute to CoreyMSchafer/code_snippets development by creating an account on GitHub.

frigid basalt
#

Yes this is a real test failure

#

response.data does not contain what you're looking for it to do, which you can tell because pytest tells you what response.data is

void quarry
#
def iter_count():
    for i in itertools.count():
        if i == (100 - 1):
            break

t1 = 0
t2 = 0

#test one
my_setup = 'from __main__ import itertools'
t1 = timeit.timeit(setup = my_setup, stmt ="""for i in itertools.count():
                                                    if i == (100 - 1):
                                                        break""", number = 5000)

#test two
my_setup = 'from __main__ import itertools; from __main__ import iter_count'
my_stmt = 'iter_count()'
t2 = timeit.timeit(setup = my_setup, stmt = my_stmt, number = 5000)
#

Why does Test Two run about 5% faster on average?

hexed cloak
#

Does it see itertools as a local?

ember maple
ember maple
hexed cloak
#

Oh I misread it

#

Yep i is a global and so slower

smoky tapir
#

what's the better approach to test the calculated value of its diffrence of expected?

for instance I've calculated 3.13784 and try to compared it with pi value 3.14 and I wanted to test passed if the value difference in 1e-3 or 1e-2

spark zenith
#

subtract?

azure torrent
#

is it possible to perform unit testing on:

def plot_routes(seen, adjacency_matrix):
    paths = dict() 
    dijkstra(seen, adjacency_matrix, paths) 

    node_values = [] 
    for plot_node in paths.keys(): 
        add_node = [plot_node, 0] 
        while paths[plot_node] != plot_node: 
            add_node[1] += 1 
            plot_node = paths[plot_node] 
        node_values.append(add_node) 

    return node_values, paths
spark zenith
#

yes. seems like something that'd be pretty straightforward to test

azure torrent
#

I havent really gonna into testing alot on python

spark zenith
smoky tapir
hexed cloak
azure torrent
hexed cloak
#

Just assert on anything you want and then look at the error message

#

If the code is already written it's "legacy code" so you have to assert on the current behaviour

void quarry
# hexed cloak Yep `i` is a global and so slower

to be clear, are you referring to the variable i in the string literal of Test One as being a global variable and the other variable i in the function definition, iter_counts(), as being a local variable?

void quarry
spark zenith
bitter wadiBOT
#

@spark zenith :white_check_mark: Your eval job has completed with return code 0.

001 |   4           0 LOAD_GLOBAL              0 (itertools)
002 |               2 LOAD_METHOD              1 (count)
003 |               4 CALL_METHOD              0
004 |               6 GET_ITER
005 |         >>    8 FOR_ITER                 9 (to 28)
006 |              10 STORE_FAST               0 (i)
007 | 
008 |   5          12 LOAD_FAST                0 (i)
009 |              14 LOAD_CONST               1 (99)
010 |              16 COMPARE_OP               2 (==)
011 |              18 POP_JUMP_IF_FALSE       13 (to 26)
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/zoqegizayu.txt?noredirect

void quarry
void quarry
# spark zenith hypothesis is looking good

Are these the relevant conditions to consider?

Function call with local variable

10 STORE_FAST               0 (i)

5 12 LOAD_FAST 0 (i)


Use of global variable
10 STORE_NAME 2 (i)
2 12 LOAD_NAME 2 (i)Are these the relevant conditions to consider?

spark zenith
#

I mean, the main thing to do here is to spot the difference between the two disassesmblies

#

but yeah, that's the part to focus on

void quarry
#

At my level of experience w/ Python, I'm used to expecting that a dictionary is faster to access then a list. So this discussion seems a little counter intuitive in this problem since as @ember maple seems to be saying that the local variable is utilizing a list and the global variable is utilizing a dictionary. Perhaps the concept for me to focus on though is this concept of local variables being optimized and the terms STORE_FAST and LOAD_FAST

ember maple
void quarry
#

beyond me...... for now

spark zenith
#

finding a thing in a list is slower than looking that thing up in a dict, but looking a thing up in a list is faster than looking a thing up in a dict

#

i.e. 'apple' in list_of_fruit is slower than dict_of_fruit['apple'] but list_of_fruit[1] is faster than dict_of_fruit['apple']

#

(and the bytecode generator knows which index each variable is in so it can index into the array directly)

void quarry
#

aaaahh ๐Ÿ’ก

ember maple
#

๐Ÿคฆโ€โ™‚๏ธ shoulda put that in parens behind "fast locals"

spark zenith
#

(I guess because the list of variables in a function is known at compile time but the list of globals in a module can change when some nutjob does import yourmodule; yourmodule.x = 'surprise')

void quarry
#

Thanks. This is all good food for thought.

tidal rock
#

how sure are you about the 5% difference? i ran the code and cant reproduce this. the results vary quite a lot. sometimes test 2 is even much slower.

#

(python 3.9.10 running on win 10)

void quarry
#

5% difference was a ball park. the times I ran it it does vary, but anecdotally that's what I noticed. (Python 3.7 on Windows)

tidal rock
#

tbh i wouldve expected test 2 to be consistently slower due to function call overhead

void quarry
void quarry
#

Average of percentage benefits of Test Two verses Test One ran 50 times: 5.45%

proper wind
#

Hi, I desperately need help writing unit tests for my proxy server (HTTP) only. I am trying to use my proxy to do the testing, but it all just ends up in dog shit.

#

Here is my proxy

#

Here is my test-file

#

As you can see it is a lot of comments from various tries....

#

ideas?

hexed cloak
proper wind
hexed cloak
#

webbrowser.open will try to open the page on your server btw

proper wind
#

its just says collecting but nothing more happens

#

when I force stop with ctrl C I can see that it has fetched urls I have visited

hexed cloak
#

You need to move your run_forever call into a:

import sys

...

def main():
    httpd = ...
    httpd.serve_forever()
    return 0

if __name__ == "__main__":
    sys.exit(main())
proper wind
proper wind
#

I mean it doesn't really redirect, but when user tries to enter a blocked domain it shows a 301 and open youtube and Rick Rolll the user

proper wind
#

like this?

#
from http import server
import urllib.request
import webbrowser
from .db import webBlock_db
import sys

database = webBlock_db()

# database.create_table()

# add a website to tabel in database

# database.add_one('http://httpvshttps.com', 'www.httpvshttps.com')

PORT = 8000
BLOCK_DOMAIN = database.show_all_blockes()
print(f"This is all the blocked domains: {BLOCK_DOMAIN}")


class MyProxy(server.SimpleHTTPRequestHandler):

    def redirect_to_new_website(self):
        newUrl = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
        print("redirecting due to banned website")
        return newUrl

    def do_GET(self):
        # print('request received from browser')
        url = self.path[1:]
        if url in BLOCK_DOMAIN:
            newurl = self.redirect_to_new_website()
            webbrowser.open(newurl)
            # url = newurl
            self.wfile.write('Bad website'.encode())
            self.send_response(307)
        # Headers send cookies, session data etc
        self.send_response(200)
        self.end_headers()
        self.copyfile(urllib.request.urlopen(url), self.wfile)

httpd = socketserver.ForkingTCPServer(('', PORT), MyProxy)
print("listening...")


def main():
    httpd = ...
    httpd.serve_forever()
    return 0

if __name__ == "__main__":
    sys.exit(main())```
hexed cloak
#

Also avoid using a global database

#

Make a constructor in your class that takes a database connection

proper wind
#

perhaps I could only just declare the db in the do_GET func?

hexed cloak
#

No use a constructor

#
def __init__(self, *args, **kwargs, database):
    super().__init__(*args, **kwargs)
    self._database = database
#

Then in your test you can pass in a temporary database

proper wind
#

I use a :memory: swlite db

#

sqlite*

#

@hexed cloak as for testing, what do you suggest?

hexed cloak
#

You'd call MyProxy(database=database)

proper wind
#

ok, and then? how do I for instance assert status_code?

hexed cloak
proper wind
hexed cloak
#

Are you using git to make sure you can undo changes with confidence?

proper wind
#

I am using git, but not as frequent (I am a beginner so not use to commit as often as one might should)

hexed cloak
#

Can you show the error you were getting and your new code

proper wind
#

I have to change it back, one sec

#

first error

#
        super().__init__(*args, **kwargs)
        self._database = database```
#

def init(self, *args, **kwargs, database):
database marks red with error

#

Parameter cannot follow "**" parameterPylance

#

I did however try to remove databas and set self._databse = webBlock_db()

#

(my database class)

#

And this is the error

#

BLOCK_DOMAIN = database.show_all_blockes()
print(f"This is all the blocked domains: {BLOCK_DOMAIN}")

#

no sorry, this

#

File "/home/lura/Dokument/src/python/U06/app/http_proxy.py", line 51, in do_GET
BLOCK_DOMAIN = self._database.show_all_blockes()
AttributeError: 'MyProxy' object has no attribute '_database'

^CTraceback (most recent call last):
File "/home/lura/Dokument/src/python/U06/app/http_proxy.py", line 81, in <module>
sys.exit(main())
File "/home/lura/Dokument/src/python/U06/app/http_proxy.py", line 77, in main
httpd.serve_forever()
File "/usr/lib/python3.9/socketserver.py", line 232, in serve_forever
ready = selector.select(poll_interval)
File "/usr/lib/python3.9/selectors.py", line 416, in select
fd_event_list = self._selector.poll(timeout)
KeyboardInterrupt

frigid basalt
proper wind
#

Honestly it was @hexed cloak who came up with the idea. If you scroll i bit further up you can see my version

hexed cloak
#

Can you use ```python

proper wind
#

I just need the database to contain "bad websites" and if the domain contains in the database it will be blocked

hexed cloak
#

Oh whoops it's supposed to be __init__(self, *args, database, **kwargs):

proper wind
#

oh alright, will try

#

Should I still declare database like this as well?

hexed cloak
#

Right so don't call webBlock_db() in your module scope call it in your main function

proper wind
#
    database = webBlock_db()
    httpd = socketserver.ForkingTCPServer(('', PORT), MyProxy)
    print("listening...")
    httpd.serve_forever()
    return 0

if __name__ == "__main__":
    sys.exit(main())```
#

Am I getting there? ๐Ÿ˜„

#
Exception occurred during processing of request from ('127.0.0.1', 43196)
Traceback (most recent call last):
  File "/usr/lib/python3.9/socketserver.py", line 616, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python3.9/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
TypeError: __init__() missing 1 required keyword-only argument: 'database'
----------------------------------------```
#

@hexed cloak you'll have to sum this up for me, I don't understand 100% honestly

#

eli5

#

here is my github repo, I have not pushed the changes you'll mentioned today. But perhaps it can be usefull

fiery arrow
#

Any tips on reducing the duplication when testing HTTP endpoints? Many of them have very common traits like: "requires authentication", "requires admin permissions", "rejects non-JSON requests" etc.. How do people usually test that endpoints have these properties without repeating a bunch of code for each endpoint?

hexed cloak
#

eg with functools.partial(MyProxy, database=database)

royal orbit
fiery arrow
#

I don't see how parametrize would help

proper wind
pearl cliff
#

ever since I've started doing that, it's really helped reduce boilerplate in my tests

hexed cloak
proper wind
#
    functools.partial(MyProxy, database=webBlock_db())
    httpd = socketserver.ForkingTCPServer(('', PORT), MyProxy)
    print("listening...")
    httpd.serve_forever()
    return 0```
hexed cloak
#

No

hexed cloak
proper wind
#

aa okay, so more like

#
    res = functools.partial(MyProxy, database=webBlock_db())
    httpd = socketserver.ForkingTCPServer(('', PORT), res)
    print("listening...")
    httpd.serve_forever()
    return 0```
#

??

hexed cloak
#

You can just pass it directly

#

But yeah does it run?

proper wind
#

it says I pass in 5 arguments but it only take 4

#

Dont really know where the fifth comes from

#
    super().__init__(*args, database, **kwargs)
  File "/usr/lib/python3.9/http/server.py", line 653, in __init__
    super().__init__(*args, **kwargs)
TypeError: __init__() takes 4 positional arguments but 5 were given```
hexed cloak
#

Show your full code?

proper wind
#

sure

#
PORT = 8000

class MyProxy(server.SimpleHTTPRequestHandler):

    def __init__(self, *args, database, **kwargs):
        super().__init__(*args, database, **kwargs)
        self._database = database

    def redirect_to_new_website(self):
        """Simple function to redirect user to another 
        website when trying to enter a blocked domain.
        """
        newUrl = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
        print("redirecting due to banned website")
        return newUrl

    def do_GET(self):
        """Connection function
            Fetching the URL from path.
            checks if the URL is in BLOCK_DOMAIN.
            If all is good, sends response and header and connects."""
        # print('request received from browser')
        BLOCK_DOMAIN = self._database.show_all_blockes()
        print(f"This is all the blocked domains: {BLOCK_DOMAIN}")
        url = self.path[1:]
        if url in BLOCK_DOMAIN:
            newurl = self.redirect_to_new_website()
            webbrowser.open(newurl)
            # url = newurl
            self.wfile.write('Bad website'.encode())
            self.send_response(307)
        # Headers send cookies, session data etc
        self.send_response(200)
        self.end_headers()
        self.copyfile(urllib.request.urlopen(url), self.wfile)

def main():
    # res = functools.partial(MyProxy, database=webBlock_db())
    httpd = socketserver.ForkingTCPServer(('', PORT), functools.partial(MyProxy, database=webBlock_db()))
    print("listening...")
    httpd.serve_forever()
    return 0

if __name__ == "__main__":
    sys.exit(main())```
hexed cloak
#

Remember to use ```python

proper wind
#

not sure what you mean by

#

python?? eli5 ๐Ÿ˜„

#

how do you mean I should use that? I have never done that

blazing violet
#

He means when you put a codeblock in discord

#

so type three ticks ``python

#

so it enables code highlighting like this

class Yo:
  def __init__(self, heh:str) -> None:
    self.heh = heh
proper wind
#

aah okej, thanks @blazing violet

jolly tangle
#

@frigid basalt

Just to remind you this is the error.

>           assert b'Welcome to the app' in response.data
E           AssertionError: assert b'Welcome to the app' in b'<!DOCTYPE html>\n<html>\n<head>\n    \n<title> flashblog register </title>\n    <!-- The title will say home -->\n  ...n       </form> \n            \n     <!-- From home. Prints userpost information -->\n        \n    \n</body>\n</html>'
E            +  where b'<!DOCTYPE html>\n<html>\n<head>\n    \n<title> flashblog register </title>\n    <!-- The title will say home -->\n  ...n       </form> \n            \n     <!-- From home. Prints userpost information -->\n        \n    \n</body>\n</html>' = <WrapperTestResponse 2230 bytes [200 OK]>.data

app\tests\functional\test_login.py:25: AssertionError

Here is my github it is a little out of date and needs to be cleaned up. https://github.com/NML240/flaskblog2/tree/master , I accidentally called the side branch master I plan on changing that.

In models.py remove confirmation_email: bool, reset_email_password: bool to make it work.
And in the tests folder you need to add an __init__.py file . In
flaskblog2/app/tests/unit/test_models.py remove True, False and in flaskblog2/app/tests/functional/test_login.py remove 'flask_test.cfg' like you suggested.

The odd part is the code the runs when I execute the code in run.py but the error shows up when I type python -m pytest . Any idea how to solve to this? Does this have to do with my templates that contain register.hmtl?

Sorry if I am bugging you.

Also I even tried to see if blueprints might be causing the error but I still get the same error.
https://code-maven.com/flask-blueprint-with-tests

Thanks for the help.

GitHub

flaskblog . Contribute to NML240/flaskblog2 development by creating an account on GitHub.

frigid basalt
#

For the only test I can find which appear to be relevant, it seems reasonable for the test assert 'Flask User management Example' in response.data to fail. Afterall, I couldn't find this string anywhere in the template or code?

jolly tangle
#

also I changed the code to work with register route so 200 instead of 405 etc.

Here is the line @frigid basalt

https://github.com/NML240/flaskblog2/blob/master/app/tests/functional/test_login.py

Or Am I misunderstanding your question? I don't really understand the line assert 'Flask User management Example'

Would it be easier for me to just update my github?

GitHub

flaskblog . Contribute to NML240/flaskblog2 development by creating an account on GitHub.

frigid basalt
# jolly tangle also I changed the code to work with register route so 200 instead of 405 etc. ...

The issue is that the tests are failing right? And the thing is, that it's because they should be? I am a bit confused about what my part is in this and how you got to this point if the tests are always failing?

If I look at this line: https://github.com/NML240/flaskblog2/blob/master/app/tests/functional/test_login.py#L25

Then look at the /login route, I can't find that text in the source. So the test fails, because something is wrong?

bitter wadiBOT
#

app/tests/functional/test_login.py line 25

assert b'Flask User management Example' in response.data```
primal sable
#

Is there any sort of minimum gold standard which should be reached for coverage %?

empty dust
frigid basalt
#

If you focus too much on code coverage, you start writing tests that rely on your implementation which is generally a bad thing.

royal orbit
#

I tend to go for "100% of code is either covered, or annotated as not covered" - and then the percentage doesn't matter, you just check that the annotations aren't exempting anything which really needs to be tested.

fiery arrow
#

The thing I don't like about coverage is that it heavily depends on the implementation. Write the function in one way, and it's supposedly 100% covered. Write it in a different way, and it is 20% covered.

#

And it of course doesn't check that you've asserted anything about the code. You just ran it.

#

So it's more of a useful tool to see which paths you've completely missed when testing. Also useful to find dead code. But it doesn't say much about the quality of your tests

#

(Also, include your tests into coverage sources! If some part of your tests didn't execute, it's a problem)

fiery arrow
# fiery arrow The thing I don't like about coverage is that it heavily depends on the implemen...

Example: suppose that you want to make a function called is_lowercase_letter which checks if a string is a lowercase letter.

If you use a regex or a set membership check, a test like assert is_lowercase_letter("a") will get you 100% branch and line coverage.

If you wrap the check in a no-op if-else, then you get 50% coverage! Even though the function does the same thing. Now you might add a second test with a non-letter to get back your 100%.

Then you replace the simple check with the equivalent chain of if-elif-...-else. And now your function has about 4% of coverage.

#

The "real" 100% test coverage is achieved when you test all the possible valid input combination. For example, a pure function taking three bools and returning a string could be thoroughly tested with a simple table.

#

So my main point is that the "real" coverage depends on the specification - i.e., how much of the specification space is exercised.

plush vale
plush vale
fiery arrow
plush vale
#

ah, so you enforce 100% cov, and exclude intentionally uncovered paths

#

I was wondering how to enforce that the annotations don't go out of sync with reality over time

jolly tangle
#

@frigid basalt it is suppose to be my register route I just have not modified all of my code on github like I stated and the register route works when I test it. But it fails duringassert b'Flask User management Example' in response.data .

I managed to get assert b'' to work by changing the message. What does assert b'' do?

sorry for the confusion

frigid basalt
#

!e assert b''

bitter wadiBOT
#

@frigid basalt :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 | AssertionError
jolly tangle
#

this when I go ```assert b 'register' in response.data


This is the register route even though the file is called test_login.py I have just not changed the name.
frigid basalt
#

Is the code really assert b''?

jolly tangle
#

@frigid basalt
yes.
what does assert b'' do? does it look for the phrase in the html?
would it be easier if I just updated my github? The github I linked is not up to date

frigid basalt
jolly tangle
#

@frigid basalt
Thanks for the help sorry for the million questions.

why does assert b' ' in response.data return True ?
Here is the proof. In the pic below.
It also returns True if I go assert b' register 'in response.data

But if I go
assert b'Flask User management Example' in response.data I get the error

 E           AssertionError: assert b'Flask User management Example' in b'<!DOCTYPE html>\n<html>\n<head>\n    \n<title> flashblog register </title>\n    <!-- The title will say home -->\n  ...n       </form> \n            \n     <!-- From home. Prints userpost information -->\n        \n    \n</body>\n</html>'
E            +  where b'<!DOCTYPE html>\n<html>\n<head>\n    \n<title> flashblog register </title>\n    <!-- The title will say home -->\n  ...n       </form> \n            \n     <!-- From home. Prints userpost information -->\n        \n    \n</body>\n</html>' = <WrapperTestResponse 2230 bytes [200 OK]>.data 

app\tests\functional\test_login.py:33: AssertionError   

I guess what I am asking is what does the text inside the b string do?

frigid basalt
# jolly tangle <@344404945359077377> Thanks for the help sorry for the million questions. why...

Are you relatively new to Python? assert works like normal Python, really.

assert b' ' in response.data becomes True because if you look at response.data there is b' ' inside of it (a space)

assert b' register ' in response.data also becomes True if you look at response.data there is register inside of it (see screenshot)

The reason you get the error on assert b'Flask User management Example' in response.data is because Flask User management Example is inside that string

jolly tangle
#

@frigid basalt Yep I am never used it before and response.data contains the html from the get route in register?

#

Well you highlighted the text so it must

#

dumb question

#

Does it pick up comments also and tags

#

I can expeeriment nevermind thanks @frigid basalt

frigid basalt
jolly tangle
#

Thanks for taking the time. I don't have anymore question.

proper wind
#

๐Ÿ˜’

delicate basin
#

Is that an open source project?

glass pivot
#

probably test driven dev

#

tests were made before code

maiden pawn
glass pivot
#

that's also possible, but in that case the tests were really poorly made, even with code that depends on a lot of other internal things, with monkey patching and mocks, you can still make good independent tests

spark zenith
#

yeah, nobody writes that many tests in TDD before implementing
tests can be independent but you can still break the core of your implementation

proper wind
#

To anyone curious it's an 8 year old open sourced legacy code project that my company has decided to take and enhance on behalf of the government. And I'm forced to fix this as the sole backend dev in my team. I might as well just re-write all these tests since our logic has changed so much....

#

Even the original project devs never finished these tests.

#

Like, they were broken from the very start.

#

Also I do have to say, my team and I have found SO many issues with their original code, nothing they did was ever done properly. It's truly shocking.

devout tapir
#
def display(rate=None):
    system('cls')
    s = '''Start:        {0}
Stop:        {1}
Current:    {2}
'''.format(START_DATE, STOP_DATE, datetime.now())
    if rate:
        s += 'Rate:        {0} degrees/second'.format(rate)
    print(s)```
I'm pretty new to unit testing.. been tasked with creating tests for scripts I didn't write and that no one has updated in 5-10 years (suppose I'm in a similar situation to cg here, but not quite as large in scope). So I've kinda struggled with understanding how to design unit tests for particular functions, like the one shown above (which is uncommented by the original creator). anyone willing to help me out a bit with this one? So far I really only understand very simple conceptual examples of unit test designs, for instance designing a test for a function which simply adds 2 to an input number. perhaps I just need to have conversations with the team that originally made these scripts to see what these functions are specifically intended to do?
glass pivot
#

you'll probably want to look into monkey patching, you could patch the print function and ensure that it has been called

#

but with functions like these, there isn't really that much to test

#

you could also check that the rate was included in the printed string, but that's about it

devout tapir
#

that was my thought, that there isn't much to test lol

#

what you're saying makes sense though

#

i haven't heard of monkey patching, I'll look into that

glass pivot
#
from unittest.mock import patch, Mock
import builtins

my_mock = Mock()
with patch("builtins.print", my_mock):
    print("123")
    my_mock.my_mock.assert_called_once()
    a = my_mock.call_args
    ...
#

here's a quick example of how that could look like

#

you could then check for something like "123" in a.args[0]

ember maple
#

@glass pivot i recommend to split the function up a bit, just have something that takes the optional rate and return the string, that can then just be called

glass pivot
devout tapir
#

for the checking that rate is in the printed string, something like this be the right way of thinking about it?

if rate in s:
   assert True

obviously very simplified, but just as a quick example

glass pivot
#

why not just assert rate in s

#

it already returns a boolean

devout tapir
#

ahh I see

#

this is all helpful in terms of thinking about this function and some others as well, thanks

glass pivot
#

no probs

#

though I do agree with Ronny, if you can do some refactoring on that code-base, it could make the code a lot easier to test

#

if that function simply returned the string and it was just printed from some other function, you could only test that the string it returns is valid

#

printing isn't generally something you'd need to be testing and while this does work and is fine, it's a bit odd to see in a unit-test

devout tapir
#

yeah, I'm going to have a meeting in the next couple of days with some of the people who made the scripts so I hope that'll help clear up some issues like that. I was just told to make unit tests for functions in the scripts so I took a look at each function and there are some like this that are real head-scratchers lol

ember maple
#

@devout tapir also take a look at tools like rich - which make printing updates in certain way a utter joy

verbal timber
#

anyone can help me create a mock

hexed cloak
royal orbit
spark zenith
#

woah... you're exeucting python client side to generate unittests?

royal orbit
#

Yup!

maiden pawn
#

I have files like
project
--blocks
----tests
------test_models.py
--delivery
----tests
------test_models.py

for some reason pytest works fine locally, pytest works in test explorer, but fails in pytest test explorer with error "File not found" (until i rename to test_models1.py. Any idea why?

#

I have in this project like 20-30 files like that, and renaming all of them a bit of hussle

ember maple
#

@maiden pawn try import mode importlib or adding _init.py files to the folders

verbal timber
#

Hi i have a larger amount of code I need some help with making testcases

#

its kind of related to boto3 and other stuff

#

do let me know if any one has experience

loud minnow
#

Anyone knows how to make JUnit testing for jsp?

hexed cloak
verbal timber
#

and u can check it out

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.

verbal timber
proper wind
#

Hi, I just discovered negative testing today and I would like to write one but I am having difficulty find some good docs or examples online. Does anyone know of any useful links for me please?

What I am trying to do is, I have a language field which HAS to be filled in. So I would like to write a test that if language = None then it should display an error message or a 400 status code.

frigid basalt
proper wind
#

@frigid basalt not not an if statement, an actual test ๐Ÿ˜€

frigid basalt
#

Which testing framework do you use?

proper wind
#

pytest

#

(the code uses unit test too) it is not my code but I need to add a test to it

frigid basalt
#

Okay so you should be able to get ahold of the information has this language field and then you'll want to assert the behavior you want: ```python
data = ... # Somehow get 'data' from your code
assert isinstance(data.get('language'), str)

#

Alternatively, this may turn out to be better for your test: ```python
data = ...
assert data.get('language') is not None

proper wind
#

ok cool, thanks a lot for your help @frigid basalt, that looks good

#

Can I ask if you know of any documentation about negative testing please?

frigid basalt
#

Not any kind of book or similar, sorry no. I haven't read anything like that personally

proper wind
#

ok no worries, you have helped me enough! Thanks again ๐Ÿ˜

honest crag
#

Hey there, we have a legacy wall-of-code method about 800 lines long, and we need to write tests for it. What's your method to handle such a task?

The method is swarming with SQLAlchemy calls, makes other external calls to other systems, sends out e-mails etc.

proper wind
#

Is refractoring it out of the question?

honest crag
#

No, we can refactor it. But I couldn't decide if we should abstract SQLAlchemy in order to mock it etc.

proper wind
#

I think it's probably fine to mock it without abstraction to a certain degree. If the concern is having to mock a lot of the ORM's features, I don't think that's necessarily avoidable without limiting how much you are able to do in your code.

There's always the option of using an actual database in your tests too, but that'll depend on your needs

honest crag
#

Yeah, I went with the second option. I spinned up a MySQL server for tests, dropped all tables and created all to clear all the tables but it slows down the testing, so I wanted to refactor stuff out and write unit tests. If you can pass me some resources to look into mocking SQLAlchemy I will be glad, thanks

proper wind
#

For better or for worse, I haven't had the opportunity to use it yet, but I was looking at mock-alchemy previously. It's not a complete implementation of sqlalchemy, but it's a decent start

#

That is

#

!pypi mock-alchemy

bitter wadiBOT
honest crag
#

Thanks, I'll look into it

azure torrent
#
def plot_routes(seen, adjacency_matrix):
    paths = dict() 
    dijkstra(seen, adjacency_matrix, paths) 

    node_values = [] 
    for plot_node in paths.keys(): 
        add_node = [plot_node, 0] 
        while paths[plot_node] != plot_node: 
            add_node[1] += 1 
            plot_node = paths[plot_node] 
        node_values.append(add_node) 

    return node_values, paths```

Trying to do some unit testing on this but I don't know how to
#
import unittest
from MainFYP import plot_routes

    
def test_paths(self):
    self.assertFalse(plot_routes.is_prime(4))
    self.assertTrue(plot_routes.is_prime(2))
    self.assertTrue(plot_routes.is_prime(3))
    self.assertFalse(plot_routes.is_prime(8))
    self.assertFalse(plot_routes.is_prime(10))
    self.assertTrue(plot_routes.is_prime(7))
    self.assertEqual(plot_routes.is_prime(-3),
                                    "Negative numbers are not allowed")

if __name__ == '__main__':
    unittest.main()``` 
This is my attempt, but it didnt seem to work
proper wind
#

Try putting your test into a unittest.TestCase class

#

From the docs on unittesting:

The basic building blocks of unit testing are test cases โ€” single scenarios that must be set up and checked for correctness. In unittest, test cases are represented by unittest.TestCase instances. To make your own test cases you must write subclasses of TestCase or use FunctionTestCase.

#

You can technically avoid doing classes, but that's an unrecommended approach provided for backwards compatibility

azure torrent
# proper wind Try putting your test into a `unittest.TestCase` class

like this ?


import unittest
from MainFYP import plot_routes

class testplotroutes (unittest.TestCase):
    
    def test_seen(self):
        self.assertFalse(plot_routes.is_prime(4))
        self.assertTrue(plot_routes.is_prime(2))
        self.assertTrue(plot_routes.is_prime(3))
        self.assertFalse(plot_routes.is_prime(8))
        self.assertFalse(plot_routes.is_prime(10))
        self.assertTrue(plot_routes.is_prime(7))
        self.assertEqual(plot_routes.is_prime(-3),
                                    "Negative numbers are not allowed")

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

Every time I test this, it just runs MainFYP.py and not the test file

#

python -m unittest test_plotroutes.py

proper wind
#

You don't need to do both unittest.main() and python -m unittest but that's unrelated to what you're describing.

#

Do you have code in your MainFYP file that runs when the module is imported?

#

i.e any code that is not in a function or class, and isn't under if __name__ == '__main__':

azure torrent
proper wind
#

Sure

azure torrent
proper wind
#

All the code from the beginning till line 112, and from 289 till the end runs when you import the module

#

You have the option of moving the parts of it you don't want to run under if __name__ == '__main__' like you had in your unittest code

#

Anything inside that if statement will only run if you run your code as python MainFYP.py, but not if you import MainFYP

azure torrent
#

I feel like doing unit testing on that code will be a nightmare for me

proper wind
#

Well, I can't tell you what you should or shouldn't test, because at the end of the day it depends on your requirements (if you need functional testing, what feature do you wish to test?).

If you establish a better idea of what you want to test (this can be a complex problem, but it's the first step that should be taken in addressing testing), we can help guide you on how to test it. Looking at your code, you might benefit from breaking some of it up into more files. For instance, the function you are testing is a utility function, so it might make sense to place it in a utility.py file.

azure torrent
#

If you have any suggestions then i would appreciate it very much

proper wind
#

Is this a project that is being reviewed or seen by someone? I don't know why else you'd have a requirement with no reasoning. It's kind of hard to recommend anything without it.

Anyways, unittesting is one of the simpler types of testing so I guess that's what I'd go with

#

Perhaps you could explain what you don't understand about it

azure torrent
#

The testing doesnt have to be complex at all, I just need to test some components within the code and show that it works essentially

#

but producing those results im finding difficult. It may be easy for some, but im new to unit testing

proper wind
#

Testing does not exist in a vacuum, but this isn't the first non-sensical assignment I've seen.

Anyway, plot_routes seems like the best starting point here. I'd start by testing various combinations of inputs, and making sure they return the desired outputs. Make sure to test edge cases as well, where you can. One interesting note is that this function references another function, dijkstra, but the beauty of unittesting means that if dijkstra is unittested separately, you don't need to worry about it here. In other cases you can use mocking. That's another discussion though

After that I'd do the dijkstra function. Same approach as plot_routes really.

Finally, for the create_matrix function, you probably just want to test that returns the matrix you expect. You use global variables in that function instead of taking arguments, which makes it more annoying to test because it means you need to modify the context rather than just set the arguments you want, but that's not too difficult. I would recommend doing some of the "easier" functions first.

azure torrent
azure torrent
# proper wind Testing does not exist in a vacuum, but this isn't the first non-sensical assign...

Hey, sorry for pinging you but I tried something and idk if it worked or not. It says it did. So like you suggested I made a seperate file and added the functions i wanted to test and i did


import unittest
from testtest import plot_routes, dijkstra

class testplotroutes (unittest.TestCase):

    def test_dijkstra(self):
        self.assertTrue(dijkstra, 1),("Incorrect")
     
        
    def test_plot_routes(self):
        self.assertTrue(plot_routes, 1),("Incorrect")

I added some int values in there and i got this

#

Does that mean the testing was successful or did I do something dumb lol

proper wind
#

Well, so ok... hm

#

Let's break this down a bit

azure torrent
#

rip

proper wind
#

Hah dw it's small

#

self.assertTrue(dijkstra, 1),("Incorrect")
Notice the positioning of the comma here, it's after the assert true function. In this case, you can read this code as:

self.assertTrue(dijkstra, 1)
("Incorrect")

In this case, the second line doesn't actually have any effect

#

And the first line just checks whether the function (not calling it) is true or not. It'll always be true because bool(function) is true, but it's not what you want I think

#

I think what you wanted to do was call the disjkstra function, then check it's result for being true or false

#

Could you verify

azure torrent
#

Yes

#

Oh so, how should I input values in there? like int values as such

proper wind
#

Cool, cool

#

So, it might be easier to understand the general flow if we break it down a bit:

# first, we want to get the result of our function
result = djisktra("input")

# then we want to test that we got the correct thing
self.assertTrue(result)

We can simplify the above to just self.assertTrue(djisktra("input"))

#

In this case, we should refer to the function definition:

def dijkstra(source_node, adjacency_matrix, paths): 
#

It expects those three arguments, so we should test out the function with different combinations of these arguments.

#

To an extent, I'm struggling to help you with this because being any more specific would require me to start reading your algorithm and what the function is supposed to actually do, but there's no typehinting, documentation, or comments, and it's 300 lines, so it's uh... a bit of a commitment lol

azure torrent
#

Oh thats simple

#

I have a commented version

proper wind
#

One thing I'm seeing though is that your function doesn't actually return anything, so asserting true and false doesn't make sense

#

Rather, it modifies your inputs, so your test might look more like:

azure torrent
proper wind
#
source_node = Node()
second_node = Node()
# (etc)
adjaceny_matrix = Matrix(source_node, second_node)
paths = [list, of, paths]

dijkstra(source_node, adjaceny_matrix, paths)

# everything up to this point was just preperation
# everything after this point is the actual "testing"

self.assertEqual(adjaceny_matrix[source_node][0], 10)
# this makes sure that the dijkstra function "returned" (modified) the correct values
#

Fundamentally this might make no sense with your code, but the idea I'm trying to point out is you test what you want to verify

#

So if you want to verify it calculated the correct distance for the given inputs, then call it with those inputs, and check that the distance was set correctly

proper wind
azure torrent
# proper wind No need to apologize, this is helpful thanks

Oh I think I did something but idk if its correct lol

import unittest
from testtest import plot_routes, dijkstra

class testplotroutes (unittest.TestCase):

    def dijkstra(source_node, adjacency_matrix, paths, self):
        source_node = 1
        second_node = 2
# (etc)
        adjaceny_matrix = dijkstra(source_node, second_node)
        paths = [list, paths]

        dijkstra(source_node, adjaceny_matrix, paths)

        self.assertEqual(adjaceny_matrix[source_node][0], 10)
#

hmm wait i might've done something dumb again lol

proper wind
#

adjaceny_matrix = dijkstra(source_node, second_node)
Well, the function doesn't actually return anything, so adjaceny_matrix will always be None

#

More problematic though

#

dijkstra takes three arguments, not two

#

So that'll throw an error

azure torrent
proper wind
#

I may have made things more complicated by guessing what your code does before reading your comments hah

Nah just call dijkstra how you would normally call it in your main file

#

From the function definition:

def dijkstra(source_node, adjacency_matrix, paths): 
#

In your original code sample, you were calling it in plot_routes with dijkstra(seen, adjacency_matrix, paths), which meant that you were calling it with (Node(), create_matrix(), dict())

azure torrent
proper wind
#

I don't use discord frequently so it's unlikely I'll respond within a timely manner, but yeah you're welcome to ping

azure torrent
#

Thank you

fair elm
#

Can anyone help me with api testcase for file upload (python)

dull jasper
#

Can anyone please provide me some recommendations for mocking libraries ?

#

as I've mainly used JS

#

and it has good and easy to use APIs

#

Also, it provides utilities for spying using spy , stubbing using stub

#

But sinon.py has some bugs (w.r.t spying)

#

But I'm not sure of how to use it properly

#

As there's no working testsuite provided

#

Also, I'm using unittest for writing unit-tests

#

as it has low learning curve

#

And also, it has setUp and tearDown methods

frigid basalt
dull jasper
#

Yes, But does it have all the things that pytest-mock provides ?

#

For example, trying to spy on a method call and get all the info about the method call (params, what's returned, what's thrown etc)

ember maple
#

while pytest-mock indeed is a little bit more than just a thin wrapper, i prefer not to mix helping people with specific problems vs giving people incentives to go over to pytest unless its in their immediate best interest

#

im also the wrong person to ask about mocks and spys, i typicall try very hard to avoid them as i consider them deceptive

frigid basalt
frigid basalt
maiden pawn
#

just setting MagicMock

#

or using it in with construction for temporal measure

#

it can even patch imports in the with... but I don't think I wish to do it

#

because patching global stuff looks dirty to me. I tried to avoid it

primal sable
#

I've got a function that writes data to an excel sheet through pandas Excelwriter as a context manager. I mock the builtin open function because I load in data from a file and then process it to be put into the excel sheet. However, the Excelwriter uses ZipFile: archive = ZipFile(filename, 'w', ZIP_DEFLATED, allowZip64=True), which also uses the the builtin open function and I get this error: TypeError: '>' not supported between instances of 'MagicMock' and 'int' because the filename is <MagicMock name='open()' id='2230391110768'>. Is there any way I can go about getting this test to pass? I'm quite new to all of this testing stuff.

primal sable
#

A temp directory for what? I don't understand how that might fix this issue

#

Seems you can just point the mocker patch to the builtin open function for a specific file, rather than the more global builtins.open

azure torrent
#

Im trying to do unit testing on the functions but idk if im doing it correctly https://pastebin.com/WW0avCz1

from testtest import plot_routes, dijkstra

class testplotroutes (unittest.TestCase):

    def dijkstra(source_node, self):
        self.assertFalse(dijkstra.is_prime(4),6)
        self.assertTrue(dijkstra.is_prime(2),7)
        self.assertTrue(dijkstra.is_prime(3),1)
        self.assertFalse(dijkstra.is_prime(8),2)
        self.assertFalse(dijkstra.is_prime(10),-3)
        self.assertTrue(dijkstra.is_prime(7),-5)
        self.assertEqual(dijkstra.is_prime(-3),
                         "Negative numbers are not allowed")
  
    def plot_routes(paths, self):    
        self.assertFalse(plot_routes.is_prime(4))
        self.assertTrue(plot_routes.is_prime(2))
        self.assertTrue(plot_routes.is_prime(3))
        self.assertFalse(plot_routes.is_prime(8))
        self.assertFalse(plot_routes.is_prime(10))
        self.assertTrue(plot_routes.is_prime(7))
        self.assertEqual(plot_routes.is_prime(-3),
                         "Negative numbers are not allowed")
        ```
This is the testing im doing
#

results come out as OK tho

#

I dont think this is testing anything right?

hexed cloak
#

use a real file rather than a mock file

delicate basin
#

It recognizes test functions by whether their names start with test_

#

So it didn't recognize either of your functions as being tests.

azure torrent
# delicate basin Yeah, it isn't.
import unittest
from testtest import plot_routes, dijkstra

def test_dijkstra(self):
    # Arrange
    expected = True
    input_value = 1
    
    # Act
    actual = dijkstra.test_dijkstra(input_value)

    # Assert
    self.assertEquals(expected, actual)
    self.assertTrue(expected, actual)

I tried this and it still shows

#

this is also not testing anything

#

hm how do I make it test then?

delicate basin
#

Needs to be in a TestCase subclass like before.

azure torrent
#

hmm it failed

#
import unittest
from testtest import plot_routes, dijkstra

class testdijkstra (unittest.TestCase): 
    def test_dijkstra(self):
    # Arrange
        expected = True
        input_value = 1
    
    # Act
        actual = dijkstra.test_dijkstra(input_value)

    # Assert
        self.assertEquals(expected, actual)
        self.assertTrue(expected, actual)
delicate basin
#

Maybe you didn't mean to call test_dijkstra from the test?

#

It's trying to call a test_dijkstra method on the dijkstra function you imported.

azure torrent
#

def dijkstra(source_node, adjacency_matrix, paths): this is the method

#

should i try calling something like paths?

delicate basin
#

actual = dijkstra.test_dijkstra(input_value)

#

This line is the problem.

#

Just call the dijkstra function. It's a function. It doesn't have a test_dijkstra method.

azure torrent
#

or should i still define it at test_dijkstra

delicate basin
#

No, don't call the test from inside the test.

#

The test will be named test_dijkstra.

azure torrent
#

ahh

delicate basin
#

And it should call the function dijkstra that you imported.

#

Working?

azure torrent
#

like this right?

#

im so bad sorry haha

delicate basin
#

Just dijkstra, not dijkstra.dijkstra

azure torrent
#

ahh

#

i get this error

delicate basin
#

Nice. Now it's working.

#

That error is because you didn't pass all the required inputs.

azure torrent
#

should I just put different inputs

#

?

#

how do I make it pass lol

delicate basin
#

Start be not calling the function yet maybe.

#

We can do something simple that passes like self.assertTrue(True) so you can see that the test function works.

#

Then you can work on figuring out the actual thing you want to test.

#

The function takes 3 arguments, so you'll need to pass those 3 arguments to test it.

azure torrent
#

How do i add another argument to it

#

it says it needs adajcency_matrix

#

and paths

delicate basin
#

You probably don't need to worry about unit testing if you don't even know how the function you're testing is called.

#

I would try testing a simpler function to get the hang of it.

azure torrent
#

Ah ok ill try to just mess around with it

jolly tangle
#

Hi

For some reason when I try to run pytests it doesn't work for a POST request but works for a GET request.

Here is the error.
E assert 200 == 405
E + where 200 = <WrapperTestResponse streamed [200 OK]>.status_code.

Notice I am using GET and POST. So that is not causing the error. Also my register route works when I run it. The POST request also redirects you to login route if that makes a difference at the end of the route.
routes.py
@userinfo.route("/register", methods = ['GET','POST'])
I was googling it and found app.config['WTF_CSRF_ENABLED = False']. But that didn't make a difference.

The code below works for a get request but as stated not for a pytest.

app/tests/functional/test_routes.py

def test_register_page():
    """ 
    GIVEN a Flask application configured for testing
    WHEN the '/register'page requested (post) 
    THEN check that the response is valid 
    """
 
    flask_app = create_app()
    # The with statemnt allows you to open and close files safely by making sure there is no errors
    # What is test_client?  test_client makes requests to the application without running a live server
    # Use the test_client to check the route which is a post request
    with flask_app.test_client() as test_client: 
        response = test_client.post('/register')
        assert response.status_code == 405
        # checking html for the term register
        assert b'register' in response.data

My app is similar setup to this
https://github.com/CoreyMSchafer/code_snippets/tree/master/Python/Flask_Blog/11-Blueprints

Thanks for the help.

GitHub

Contribute to CoreyMSchafer/code_snippets development by creating an account on GitHub.

twilit lion
#

I looking a coursse to start with tests

frigid basalt
jolly tangle
#

@frigid basalt I must have mistyped its a 400 not 200. Sorry The exact error is E assert 400 == 405
E + where 400 = <WrapperTestResponse streamed [400 BAD REQUEST]>.status_code. Also I think it should be 302 status code instead of 405 on my part.

frigid basalt
#

Yeah that's pretty much the same thing so why don't you edit your code, or edit your tests?

jolly tangle
#

@frigid basalt I managed to get it to work. I Think I was getting 2 different errors because at first I had 2 functions with the same name. I fixed that and copied the wrong error. Turns out my research from before by using app.config['WTF_CSRF_ENABLED = False']. worked. sorry about wasting your time

#

@twilit lion if you want an answer be more exact is this pure python is it flask or django etc

potent ravine
#

This is just beautiful

kind meadow
#

34 tests taking 16 seconds seems kind of slow

#

But yes it is satisfying to see everything passing

primal sable
#

Is testing your code necessary?

versed seal
primal sable
#

Thanks. I also found neds presentation in the pins. I already do testing but wanted to reassure a colleague as he is trying to get out of it :p

proper wind
#

Hi, I am looking for some help with unit testing please. I want to run these tests and output the tests ordered by date descending (so the order would be test2 then test1) but I am not sure how to do it. Any help would be really appreciated ๐Ÿ˜€

def test1(self):
    info = {
        โ€˜pinnedโ€™: True,
        โ€˜dateโ€™: '2020-03-09'
    }

def test2(self):
    info = {
        โ€˜pinnedโ€™: True,
        โ€˜dateโ€™: '2021-02-19'
    }
bitter wadiBOT
#

:incoming_envelope: :ok_hand: applied mute to @carmine slate until <t:1652187880:f> (9 minutes and 59 seconds) (reason: burst rule: sent 8 messages in 10s).

west wigeon
#

I have a module named "main_module" that tries to import a module named "optional_module", and has different behavior depending on if optional_module exists or not. I want 100% code coverage. Can anyone point me to a resource (or even mention search terms I should try) on how to mock this?

hexed cloak
#

You can use CI to run different environments with different dependencies

#

Then combine your coverage

#

So you can use is_installed

fiery arrow
#

Open-ended question about pytest fixtures. They're cool, but using lots of fixtures that depend on each other brings about a lot of indirection and implicit coupling. You can't even "Go To Definition" on a fixture, so you need to search for the fixture and then play as an interpreter to find which of the fixtures takes precedence.

Any tips or best practices for keeping fixture setups easy to understand?

maiden pawn
#

then you will have localized in which sub fixture, the problem happens

#

may it is possible to call the fixture in a different way that test function param? ๐Ÿค”

#

if the fixture is a basically test, which we need to debug... then fixtures should be full of asserts, to avoid the need for debugging

#

so we could have easy place to find where it went wrong

maiden pawn
#

I think it says that the code smells. It is one of the three named things the book mentions when hell went loose

#

and something went wrong with its architecture

#

the code/architecture of the code should be made/remade in the way not requiring long setups
So.... the time for design patterns / architecturing better components.

fiery arrow
#

that's probably what I'm asking -- how to design tests with minimal amount of indirection and "scaffolding" or "helpers"

fiery arrow
maiden pawn
#

then u will be able to write better tests

#

as for how to do that. I am still trying to comprehend it myself. The books head first Design Patterns, Clean Architecture by robert martin and Code Complete by McConnel give some ideas

#

hmm some parts are mentioned in System Analysis and Design by dennil in Implementation phase of the app

#

some parts for re factorizing technics are mentioned in TDD by Kent Beck book, it mentions it exactly from testing angle. You should definitely check this one at least. It mentions at least exactly Design Patterns for test driven development and refactorizing for that

#

i haven't read Code Complete book yet, but I hear that it is quite recommended one to handle the problem ๐Ÿ™‚

#

i tried to read Clean Architecture one, sure it gives some ideas and understanding. it was recommended to me as a not a good option though

#

head first Design Patterns is cool one

austere dune
#

This might be the wrong channel so feel free to yell at me

#

i'm writing some code that makes API calls, some POST requests, some GETS requests

#

and it's sitting in a good spot and will pretty much always work

#

but i was like "well maybe i should put in some error handling in case others run into errors"

#

i'd never done this before though
so i found 'try/except', but it got me to thinking:
"i don't know whta errors aregoing to show up, and i don't even know how many errors COULD show up"

so really what i wanted to kinda ask was 'do programmers try to anticipate all the different errors, or do they only build it in if they thinkcertain ones might come up'?

fiery arrow
#

@austere dune The exceptions that a function can raise are part of its interface. For example, if d is a dictionary (mapping strings to strings, say) and s is a string, d[s] can only ever raise KeyError. For example, it cannot raise IOError.

#

So you if you're using a library function, its documentation should list the errors it raises

austere dune
#

oh cool, yeah that makes sense

austere dune
fiery arrow
austere dune
#

perfect

#

thanks a ton!

fiery arrow
austere dune
#

oh sure

#

yeah that makes sense i guess #unit-testing is almost like a specific sub branch of that channel

fiery arrow
#

well, it's about automated testing ๐Ÿ™‚

austere dune
#

oooooooohhhhhhhhhhhhhhhh

#

i just read the description like a monkey and thought "good enough"

sand gust
#

I have a large project with many custom modules and I'm trying to figure out the best way to structure my tests.

#

currently i have everything broken out into sub directories in a tests folder. I like this because i can click on tests and run test with coverage in pycharm.

#

but what i dont like about it is that when i have a failing case and i need to flip back to the relevant piece of code that I'm working with, I have to traverse the directories to get back to the relevant file.

mild moth
#

hello there im work on project that has selenium webdriver, so i want to stream that driver to my website. what he's doing and all interactions
is there a way to do that ?
can someone help me
thanks!

delicate basin
harsh zinc
#

Hi everyone! have you seen an open source project that in your opinion have good quality tests using pytest? thanks!

marble hatch
fiery arrow
marble hatch
#

Yep

#

I think there are cases where you might be ok with complicated design, but those are generally going to be rare with python

#

ie optimizations for speed

maiden pawn
#

from python3 manage.py shell, translation.gettext(phrase_id) is perfectly translated

#

but from pytest it is not translated

#

anyidea why translations aren't working in pytest?

#

nvm. solved.the problem was kind of obvious

#

what can be affecting pytest tests? Conftest of course!
Checked and found global fixture which disables i18n for tests

sacred frigate
#

hi

frigid basalt
sleek copper
#

I sent a link to github actions because I thought it should be easier to see what happened like that

sleek copper
#

fucking hell

#

I found the problem

#

I had a random package called pytest-asyncio-cooperative installed

#

and even though it wasn't enabled it did some stuff behind the scenes that disabled all coverage

#

๐Ÿ’€

#

I am fuckin done

sand gust
#

how do i pass an arg to a pytest fixture?

hexed cloak
sand gust
#

I was hoping there was a cleaner way than having to include with ContextManager ... in all of my test cases.

maiden pawn
#

What is correct way to insert data like this into Robot? I tried

    Create Site         slug=name      name=site_name  language=it languages={'list': ['en']}
#

i try to input languages

#

which is dictionary with list

proper wind
#

pytest vs unitest ?

glass pivot
#

ironically, python's unittest is not very pythonic in it's function names (they're cameCased, not snake_cased), and you're expected to use some custom functions like assertEqual(x, y), instead of simply doing assert x == y

pearl cliff
#

pytest will have you a lot of keystrokes, and has a better cli interface

glass pivot
#

yeah, you can use pytest's cli with unittests too though

pearl cliff
#

it's good to learn unittest because a lot of teams use it in industry, in my experience. reducing dependency count and all that

#

that is true and i always forget it. doesn't it only support a subset of unittest functionality though?

glass pivot
#

I never encountered issues while using it to run regular unittests, but it's possible it doesn't support everything, I haven't used it with unittests that much

pearl cliff
#

good to know

delicate basin
#

Hello, I'm looking for a high quality, idiomatic mocking library in Python to use with TDD. I found a list of mocking libraries here: https://wiki.python.org/moin/PythonTestingToolsTaxonomy
There's a link to what's supposedly a side-by-side comparison of the libraries listed, but it 404s. (yay! ๐Ÿ˜’)

maiden pawn
pure holly
#

the main advantage to unittest is that it's in the standard library

delicate basin
#

Thanks so much bobob!

quaint reef
#

Hi there,
Quick question,

I have an application in docker, i wrote some selenium test for it. It is on github action, so whenever someone push to master the github action setup the the application from docker and runs the test.

My question, it is possible on code /test level to check if the webpage is loaded from docker?

I dont really want to use thread sleep or github action sleep.

proper wind
#

Hi, I am fairly new to writing tests. Could you send links to the resources (maybe a article/YouTube video) that helped you to learn testing in python?

delicate basin
proper wind
#

Nice, thatโ€™s what I have been looking for. Thanks ๐Ÿ™๐Ÿป

hot oxide
#

Which would you choose , pytest vs selenium vs unittest for django ?

proper wind
#

pytest and unittest are used for unit testing, whereas selenium is used for UI testing.

#

And pytest has more features, is more readable than unittest

hexed cloak
#

you can use pytest with selenium

#

Django has its own test runner and test discovery that integrates with Django's lifecycle and globals

#

There's pytest-django that helps integrate pytest's lifecycle into Django's and it works pretty well but not 100%

#

I still prefer pytest-django

past wave
#
def test_very_very_very_very_very_very_very_very_long_function_name():
    ...

How do you guys deal with long test function names in pytest . Is there any way to add a description?

lapis gale
#

Docstrings?

#

You may also groub them in test classes or in different files

delicate basin
#

My names stay long. I keep them under 80 characters though, by rewording them if necessary to be more concise.

wild granite
#

Hi django developers,
I had a prblm with pytest transactions
I'm trying to test django-filter with transactions=true but it not working
When i run every single function alone it work fine but i run all the class it not run

astral raft
#

Hi guys. I'm solving algorithms on a site called code assess. They asked me to write test cases to check if the code is right. Wanted to ask, does anyone know how to write a test case in an editor.

On my IDE I just write

 test_function():
    assert something something. 

Does not work in the editor though

I would like an idea of what to do and then I can write the test cases properly.
Here's an image of the solved assessment but with some failed tests.

dull jasper
#
Tests structure:

\tests
  \clients
  \use_cases
    \user
      \events
        .test_output_event_consumer.py
      .test_user_transformer.py
#

My folder structure for tests is like above

#

And pytest recognises .test_user_transformer.py as a test but it doesn't recognise \events\.test_output_event_consumer.py as a test

#

Can anyone please help me out

#

I want to run all the tests inside the folder \tests irrespective of tests at any sub-directory. All of them must run.

wary relic
#

should every function be tested when working on personal project?

sand gust
#

if you want. It's your project.

faint canyon
# wary relic should every function be tested when working on personal project?

Sounds like you're trying to practice test-driven development on a personal project. I'd suggest watching this video for a better understanding of how deep testing should go: https://youtu.be/bvRRbWbQwDU

In this 2nd of a 12 part series on desirable properties of tests, Kelly Sutton and I discuss the property that tests should be insensitive to changes in the structure of the code. For a list of all 12 properties see https://medium.com/@kentbeck_7670/test-desiderata-94150638a4b3.

Episode 1: tests should be sensitive to the behavior of the code: ...

โ–ถ Play video
sand gust
#

is it really valid to combine line coverage and branch coverage like coverage.py does? that seems a bit hokey

deep dew
#

My patch methods in my test suite are not able to correctly locate objects which are supposed to get mocked

#

All right, nvm, the problem was I was searching for FinanceApp.FinanceApp... path instead of FinanceApp.Database...

karmic arch
#

can someone tell me why in hell i get an error ValueError: invalid literal for int() with base 10: '' on this code right here ```py
n = int(input())

for i in range(n):
current_num = int(input())
if current_num % 2 != 0:
print(f"{current_num} is odd!")
break

#

i enter 3 first and then i enter another number, no spaces, nothing unusual and it just pops up that error

#

that error is supposed to pop up for example if i have an int and i enter in for example 4.3

#

no idea why it gives me the error there :/

#

i can work around the error for sure, all i wanna know is why im getting it, is it some sort of bug or ?

pine yarrow
#

num1 = float(input("Enter First Number: ")
op = input("Enter operator: ")
num1 = float(input("Enter Second Number: ")

if op == "+":
print(num1 + num2)
elif op == "-":
print(num1 - num2)
elif op == "/":
print(num1 / num2)
elif op == "*":
print(num1 * num2)
else:
print("Invalid operator")

#

I have a error with line two

#

and im not sure how to fix that

#

i was working on a simple calculator

karmic arch
#

in line 1 and 3 your variable names are the same, never do that

#

let me give u an example

#
x = 3
x = 10
print(x)
#

this will print 10

#

if u want 2 individual numbers, make the variable names different

pine yarrow
#

so print(x1) if you want 3

#

and print(x2) if you want 10

karmic arch
#

on line 19 u have an empty string

#
        elif op == "":
#

it should be ```py
elif op == "*":

#

i think thats what u want

karmic arch
#

also on line 20

#

u dont have a comma between num1 and num2

pine yarrow
#

i think it took away this when i posted it

karmic arch
#

oh oke

#

wait one sec im trying to understand smth with the code

#

ah wait

#

u forgot brackets

#

the first 3 lines are ```py
num1 = float(input("Enter First Number: ")
op = input("Enter operator: ")
num2 = float(input("Enter Second Number: ")

#

there must be one more bracket at the end of line 1 and line 3

#

on line 1 u have two opening brackets aka (

#

and u need to close each open bracket every time

#

with a )

pine yarrow
#

I changed that and it gave me 12 more errors lol

karmic arch
#

well, there are many flaws with this code

#

but dont worry

#

everyone starts somewhere

pine yarrow
#

I followed a video so, im surprised it didnt work honestly

karmic arch
#

mm wait

karmic arch
#

indented basically means 4 spaces forward in simple terms

#

here is how it should actually look ```py
num1 = float(input("Enter First Number: "))
op = input("Enter operator: ")
num2 = float(input("Enter Second Number: "))

if op == "+":
print(num1 + num2)
elif op == "-":
print(num1 - num2)
elif op == "/":
print(num1 / num2)
elif op == "*":
print(num1 * num2)
else:
print("Invalid operator")

pine yarrow
#

thats just how the program did them. i'm not sure how to change those

karmic arch
#

well, next time if u have a problem or smth feel free to ping me , im not that that experienced in python but i have a couple of months on it

#

if u have questions feel free to ask

pine yarrow
#

alright thank you

karmic arch
#

keep on learning ๐Ÿ‘ ๐Ÿ™

karmic arch
# karmic arch

the issue got fixed by changing from pycharm to vs code

#

this some bs

pine yarrow
#

XD mine?

pine yarrow
#

Hi i am back

#

So I am following this video and I cant get the total to show up or the string of words to follow on the last line am I messing something up?

#

print("Welcome to Carpenter Bee Resturuant!!!!! \n")

name = input("May I ask what your name is? \n")

respone = input()

print("Welcome " + name + ", Thank you for joining us today.\n")

response = input("\n Would you like to see our menu? \n")

response = input()

menu = "Alfredo with crab meat, Grilled shrimp with homemade sauce, A baked potatoe with choice of meat added such as lobster."

print(name + ", What sounds good to you toaday? Here are a few of the favorites. \n" + menu)

order = input()

price = 20.65

tax = .14

print(" And what would your drink be today? \n")

drink = input()

total = input(price * tax)

print("Sounds good. " + name + " Your " + order + " and " + drink + " will be right out to you!!")

print("I hope you enjoyed your meal, your total comes out to " + total)

wary relic
#

I have bunch of tests which use different dictionaries as argument and compares them, is there a way to make this more elegant?

@pytest.mark.parametrize(
        "existing, new, expected",
        [
            (
                {
                    "food": {
                        "keywords": ["penny"],
                        "account number": ["DE88 5007 0010 0175 5263 03"],
                    }
                },
                {"fuel": "gas station"},
                False,
            ),
            (
                {
                    "food": {
                        "keywords": ["penny"],
                        "account number": ["DE88 5007 0010 0175 5263 03"],
                    }
                },
                {"food": "market"},
                True,
            ),
        ],
    )
    def test_category_novelty(self, existing, new, expected):
        """
        docstring
        """
        json_handler = JsonHandler()
        result = json_handler.category_novelty(existing_entries=existing, new_entry=new)
        assert result == expected
kind meadow
#

Also keep in mind that the @pytest.mark.parametrize decorators can be stacked.

jolly tangle
kind meadow
#

If an endpoint which redirects needs to be tested, then follow_redirects=True is useful because it lets the client go to the redirected location.

#

But if none of your endpoints use redirects, then you don't need to worry about that line when testing.

jolly tangle
#

@kind meadow Thanks I just couldn't understand the phrasing I understand a redirect.

fair elm
#

can anyone help me out in mocking s3 objects? I'm facing problem in doing so...

#

also
can anyone tell me , what's difference between /path/file.tst and path/file.txt
Is this two are same or different?

frigid basalt
foggy willow
#

@fair elm...and the path -without- the / on the left, is called a "relative" path, while the one -with- the / on the left, is called "absolute"

proper wind
#

Also one of those has a tst extension, while the other has a txt extension, so I suspect they might have been asking about that

#

I don't recognize tst as a common extension, it might just be a text file with a fancy extenstion

foggy willow
#

oic, you may have typoed the extension on one of them

fair elm
#

Thanks @frigid basalt @blazing sierra

#

Do anyone has hands-on in mocking s3 bucket object for testcase to pass?

tacit shadow
#

Hey

proper wind
#
def active_issues(repo: Repository) -> None:
    logger.info(f"Count active issues\n")

    project = prompt("Which project?", list(repo.get_projects()))

    column = prompt("Which column?", list(project.get_columns()))

    cards = list(column.get_cards())

    logger.info(f"> There are {len(cards)} active issues in this column.")
#

How can I decouple this method from user input so that it's more easily unit testable? I reckon that in it's current state I would have to mock the prompt method. At the same time, if I simply put project and column as parameters, and ask for user input in main() (the caller), all that accomplishes is that I will have to mock prompt in main() instead of active_issues().

frigid basalt
#

You can't, in this case, test project.get_projects() and project.get_columns() and column.get_cards() separately - then you can have an overreaching test for this specifically

mortal pike
#

When i'm testing a class with pytest, what is considered as best practice:

  1. setting protected members of my class which i want to test for my unit test

or

  1. creating mocks for the elements i need to setup for performing the unit test
pearl cliff
#

the goal is to make the tests robust to refactoring of internals

mortal pike
pearl cliff
mortal pike
#

I'm just asking because pylint is complaining about accessing protected underscore variables.

#

Ok, so i can basically stick to practices i also do for my c++/c testing.

pearl cliff
#

yeah pylint just doesn't understand this situation

mortal pike
#

I'm pretty new to python, so this was not 100% clear to me

pearl cliff
#

i don't use a linter in general. too many false positives and not enough useful information

mortal pike
#

i started using it because i'm not to familar with best practices in python in general and thought it would show me at least a few of some them ๐Ÿ˜„

#

for now i excluded the tests from pylint ๐Ÿ˜„

#

but vscode is ignoring this exclude, but this another topic, where i hope to find out why it behaves like that.

hexed cloak
mortal pike
#

I used it for testing class that does serial communication in a own thread, which sets internal class members (adding read bytes to a buffer, setting how much bytes were awaited, a.s.o)

More detailed for testing the function that does this processing. This function basically handles a state machine.

Has this a bad smell? ๐Ÿ™‚

#

I felt that it's better to set the private members accordingly to test the single states of this state machine. But maybe it is better idea to split up the action triggered in the different state into own function and test them individually. And pass the variables to that call instead of using function members.

hexed cloak
#

Then test that in isolation

mortal pike
#

Hmm. Let me think about that approach, the communication class currenlty works asynchronous, it just uses callback to pass back the read data and the data to be send out.

royal orbit
mortal pike
#

For my understanding i've already done liked described there. With one difference that I use @vernal lake to simulate reading, writing and query available date on the serial interface.

#

In c++ i would have followed that approach a little bit different by encapsulating the Read/Write/BytesAvailable functions in an abstract class. which i can exchange for unit testing.

hexed cloak
#

Some IO systems don't even have read availability eg windows IOCP

lusty horizon
#

Hi, could I ask a question about unit testing please?

if expect_raises is not None:
  with pytest.raises(expect_raises):
    npt.assert_almost_equal(patient_normalise(np.array(test)), np.array(expected), decimal=2)

I understand, when expect_raises is not None, npt.assert_almost_equal(patient_normalise(np.array(test)), np.array(expected) is executed, when patient_normalise is called and gives an error.
But what happens then in the next line if expected=None and patient_normalise(np.array(test)) ends with an error?
I doubt that npt.assert_almost_equal can check for equality in arrays with None, np.array([None]) or yes?
My test fails, but with a 'ValueError' instead of a TypeError and the testdata set is (3, None, TypeError) with test, expected, expect_raises

And in the pytest execution it fails with

if len(data.shape) != 2:
>           raise ValueError('inflammation array should be 2-dimensional')
E           ValueError: inflammation array should be 2-dimensional

because surely, if data=3 and even with np.array(data), the length is not equal to 2. And a ValueError is not a TypeError.

bitter wadiBOT
#

:incoming_envelope: :ok_hand: applied mute to @jolly tangle until <t:1653454800:f> (9 minutes and 59 seconds) (reason: newlines rule: sent 112 newlines in 10s).

carmine sage
#

!unmute 828683380974551041

bitter wadiBOT
#

:incoming_envelope: :ok_hand: pardoned infraction mute for @jolly tangle.

jolly tangle
#

Hi I am going to send my question in parts because it is to long

conftest.py

from app.models import User 
import bcrypt 
import pytest 
from app import create_app
from app import db

 
# function for tests_models.py
# The scope='module' fixture allows you to pass in the function many times


@pytest.fixture(scope='module')
#why won't this work? def new_user(plaintext_password='jotpjgjbgt')
def new_user():
    
    ''' 
    Given a User model
    When a new user is being created 
    Check the User database columns
    '''
    
    # why can't I go plaintext_password() instead of plaintext_password 
   
    plaintext_password = 'jotpjgjbgt'
    hashed_password = bcrypt.hashpw(plaintext_password.encode('utf-8'), bcrypt.gensalt()) 
    
    user1 = User(username='ugbuighiug' ,email='sefefo3240@svcache.com', hashed_password=hashed_password)
    return user1
 


# function for test_routes.py 

@pytest.fixture(scope='module')
def make_app_run_in_test_env():
    flask_app = create_app()
    # The with statemnt allows you to open and close files safely by making sure there is no errors
    # What is test_client/.make_app_run_in_test_env?  test_client makes requests to the application without running a live server
    # Use the test_client to check the route which is a get request
    with flask_app.test_client() as testing_client: 
        # What is this line?
        with flask_app.app_context():
            yield testing_client

   
# function for test/routes.py
@pytest.fixture(scope='module')
def init_database(make_app_run_in_test_env, new_user):

    make_app_run_in_test_env
    # Create the database and the database table 
    db.create_all()
    # Insert user data
    # fill out the data that is new.  

    
    db.session.add(new_user)
    # Commit the changes for the users
    db.session.commit()
    yield  # this is where the testing happens!

    db.drop_all() # delete table after use

#

**test_routes.py **

# Each function needs test infront of it to work
def test_valid_login(init_database, new_user, make_app_run_in_test_env):
    """
    Given a flask app tests if it runs  
    When I check to make valid login and logout (POST) request
    Then I should be able to check login and logout using pytest
    """
 
    
    current_user = init_database(make_app_run_in_test_env, new_user)
    # If an endpoint which redirects needs to be tested, then follow_redirects=True is useful because it lets the client go to the redirected location.
    # let me check
    # can I just ask a very stupid question in my redirect route in the post request I redirected to the home page. 
    # So response == 200 is fron the home page?
    data = current_user 
    response = make_app_run_in_test_env.post('/login', data,  follow_redirects=True)
    assert response.status_code == 200
 
    response = make_app_run_in_test_env.get('/logout', data, follow_redirects=True)
    assert response.status_code == 200
#

I am trying to get test_valid_login to work but am getting the error

init_database = None, new_user = <User 'ugbuighiug'>, make_app_run_in_test_env = <FlaskClient <Flask 'app'>>

def test_valid_login(init_database, new_user, make_app_run_in_test_env):
    """
    Given a flask app tests if it runs
    When I check to make valid login and logout (POST) request
    Then I should be able to check login and logout using pytest
    """
  make_app_run_in_test_env = make_app_run_in_test_env()

E TypeError: 'FlaskClient' object is not callable

app\tests\functional\test_routes.py:42: TypeError

How do I fix this ? thanks for the help. I am going to try one thing if it works I will let everyone know

https://gitlab.com/patkennedy79/flask_user_management_example/-/tree/main/tests Here is the tutorial I am using for pytest. My code is slightly different I can add the rest through github if anyone wants me to.

foggy willow
#

@jolly tangleat your option, you could use something like this: if you have nc installed, you can pastebin the output of an arbitrary command, for example ls -CF if you run it like this: ls -CF | nc termbin.com 9999

#

and for files, you could: cat /dir/anotherdir/something.py | nc termbin.com 9999

#

(most of this assumes you're running linux or alike, such as macos)

jolly tangle
#

@foggy willow I running windows if that makes a difference I have to go now for now. I will be back eventually

foggy willow
#

what is the command then...

#

so there are two issues... one, installing nc or netcat... two, if you want to pastebin a file, how do you do it... are you aware of the three streams created when you run a new program?

#

ok, have a good day... maybe we'll work on this later

#

all that said, it doesn't seem like people mind long posts, although the bot did something to you temporarily

glass pivot
#

just using any kind of pastebin would probably be fine, there's no need to go with termbin.com, I agree that it is cool for people who know what they're doing, but honestly, it's much simpler to recommend something like paste.gg, or hastebin instead

foggy willow
#

@glass pivotyou mean given a lot of the folks here are running windows?

glass pivot
#

yes, but even for some people running mac or linux, people often just aren't very familiar with netcat, or even aren't that comfortable in working within terminal environment, and may not know what something like cat does, but everybody here will probably understand a simple graphical interface that pages like paste.gg offer

foggy willow
#

I'm guessing that if they were running linux, it would be easier to install nc

#

it would be handy to understand stdin, stdout and stderr streams

glass pivot
#

perhaps, and yet I'd still suggest something else, because again, even linux users often aren't that familiar with these tools, and websites like this are honestly just really easy to grasp, why introduce more complexity when it's not necessary

#

(and that's comming from a guy running arch btw)

foggy willow
#

yep, you have to know stuff to install arch ๐Ÿ™‚

glass pivot
#

kind of, not really, I mean, the arch wiki makes it very simple, you really only need to follow some instructions if you're going to go with some simple DE, but yeah, if you don't know your way around a linux system, don't use arch

#

either way, that's a bit off-topic here

foggy willow
#

it's really your audience that's the main concern

#

as far as I've seen, your audience is mostly running windows

#

that said, your audience learning python, they have (or will get) enough knowledge to handle this

#

yeah ok ๐Ÿ˜‰ /me moves out of the way ๐Ÿ™‚

glass pivot
#

the fact is, that most people are going to be running win, and even if that were to change, most people still wouldn't even know how to open a terminal, and yeah, in this community, that ratio is a lot better, but I mean, why even bother with explaining all of that if the only thing that was needed was a simple paste service page, without the need to explain standard input/output/error, netcat program, how to use cat to print out file's content, what's piping, and why they should do this instead of just pasting their code to some webpage that they can do relatively quickly anyway

foggy willow
#

open a terminal? I would think that's necessary to run or especially learn python

glass pivot
#

this discussion isn't unit-test related

foggy willow
#

ok, what's the most common way, and module, to use for testing? also same question as it applies to django (note, I'm also running linux)

glass pivot
#

I think django has it's own testing framework

#

but I'm not very familiar with that

foggy willow
#

ok I'll look into that then

foggy willow
#

so howbout for plain (non-django) python?

glass pivot
#

I'd recommend pytest if you're fine with it being an extrnal library

#

if you insist on stdlib only, python does have it's own unittest module

foggy willow
#

you mean one I might have to install, and one I'd have to import?

glass pivot
#

however ironically, pytest is more pythonic in it's function/class naming, and implementation than unittest is

foggy willow
#

sure, I'm fine with that

glass pivot
#

pytest is way simpler to work with and gives you a bit nicer cli output than pure unittest

foggy willow
#

so... is unittest more "on topic" here, than pytest?

glass pivot
#

no, both are unit-testing framework

foggy willow
#

ok

glass pivot
#

unittest is a module allowing unit-tests to be implemented

#

so is pytest

foggy willow
#

ok, thanks... I'll check that out, maybe more questions later ๐Ÿ™‚

fiery arrow
#

well, both are useful for all kinds of tests

#

||like giant parametrized tests with actual control flow that use a complicated tree of fixtures please help me||

hexed cloak
fiery arrow
hexed cloak
#

and then plugins

fiery arrow
# fiery arrow Time to add `!important` from CSS
def test_god(
    pytest_important,

    first,  # !important,
    idontcare, 
    firster,  # !important !important
    firstiest,  # !important !important !important
):

and then the plugin will parse the comments!

#

Imagine if Python had decorators for function parameters, like in Java

#

I guess annotations kinda do that though

glass pivot
#

is it like an equivalent to: ```py
def foo(x):
x = decor(x)

fiery arrow
glass pivot
#

huh, I see

sinful smelt
#

Hello folks I am trying to contribute to oppia organization and have found a good first issue https://github.com/oppia/oppia/issues/15090 . But here I have to write pylint checks which I don't know anything about. If someone here who knows about pylint could suggest me some relevant resources that can help me to solve this issue. It would be really appreciated!!!

stray iris
#

Hi all, super general question. What is the purpose of "unit tests" and what can go wrong if you don't use them?

hexed cloak
#

Sounds like an interview question. I've worked on projects that only had regression tests and instead relied on rapid prototyping, monitoring and deployments with easy rollbacks

hexed cloak
stray iris
#

@hexed cloak thanks for your response! I have a job unrelated to programming and I'm self taught so I'm really having to learn the basics from first principles. My current (for fun) project is a wikipedia-like website for music. So I'm interested in saving snapshots of the site where I can roll back if users maliciously change the sites content.

#

Does this sound like a use case for a unit-test?

#

Or am I off the mark completely? lol

hexed cloak
#

Unit tests apply only to the code in the system under test - most often a specific git commit

#

Backups usually call for a drill rather than unit tests

#

Or a Disaster Recovery plan and risk assessment

stray iris
#

Okay, thank you!

#

This is only tangentially related, but do you know how a site like Wikipedia prevents malicious edits?

hexed cloak
stray iris
#

Gotcha! Thanks again ๐Ÿ™‚

kind meadow
#

@hard vessel You're running the command outside of lib, so Python cannot find the core package. If you cd lib and then run the command, it should work.

#

Maybe your intention is for core, utils, etc to all be under one package named lib. In such case, lib should contain an __init__.py, and your imports should be like from lib.core import ...

hard vessel
#

Ah, I see. Well, one of the moderators (or helpers?, not sure) helped me achieve this by doing: PYTHONPATH=lib pytest

#

I'm just running it via coverage now, but same results.

#

Thank you for your help regardless

kind meadow
#

Ehhhh I am not a fan of messing with PYTHONPATH/sys.path to get imports working

chilly helm
#

Hello! This may be unrelated to testing but here I go anyway:
I want to start TDD dev, so i created

proj_fold/
     -tests/
         -test_main.py
     -app/
         -main.py

in test_main.py it write import main but I can't figure out why it doesn't find main.py, I looked sys.path and gave me the tests directory, not the proj_fold directory ๐Ÿค” .
Can anyone help me? Thanks!

kind meadow
#

And to run the test your current directory needs to be proj_fold

chilly helm
#

Thanks Mark! ๐Ÿ˜„
Mmm I tried, but I got this error:
from app import app
and then in the proj_fold, run pytest .

tests\test_terminal.py:1: in <module>
    from app import main
E   ModuleNotFoundError: No module named 'main'

Maybe I have some config wrong? ๐Ÿค”

sour barn
#

ah

#

looks like wrap

#

amirite ?

chilly helm
hard vessel
livid herald
#

Hi guys. I have a simple scaling function looking like this:

#
    '''
    Scaling features

    Parameters:
        df (pandas.DataFrame): Dataframe on which to operate
    Returns:
        pandas.DataFrame
    '''

    scaler = StandardScaler()
    x_train = df.drop(['Transported'], axis=1)
    scaler.fit(x_train)
    scaled_data = scaler.transform(x_train)
    scaled_data = pd.DataFrame(scaled_data, columns=x_train.columns)
    scaled_data.insert(loc=0, column='Transported', value=df['Transported'])
    return scaled_data```
#

how can i write a simple test to see if scaling was done properly?

#

right now i have something like this but I dont know how to check by assert if all values where scaled

#
    """
    Test scaling_features function
    """
    test_data = {'test': [1,2,3,4,5,6,7,8,9,10,11,12],
                'Transported': [True, False, True, False, True, False, True, False, True, False, True, False]}
    df = pd.DataFrame(test_data)
    df = scaling_features(df)
    assert df.dtypes == np.float64```
fiery arrow
#

unittest.mock tip of the day: it you're patching the __exit__ or __aexit__ method with a mock, don't forget to set the return_value on the mock to None or False. Otherwise the context manager will swallow all exceptions, which you probably didn't want.

river swift
#

@echo off
color 02
:start
echo %random% %random% %random% %random% %random% %random% %random% %random% %random% %random%.
goto start save as bat file and run as administrator and you will see a matrix rain.

ocean yoke
#

Does anyone know any docs I can read or have any experience with python unittest, testing a function -> function instantiates a class -> that class has a decorator on it. I seem to mock the Class but the decorator not being mocked seems to cause issues, I tried also mocking decorator before the import of the unit under test, to no avail

hexed cloak
ocean yoke
hexed cloak
#

Ty

ocean yoke
fiery arrow
#

@ember maple do you mind if I pin this?^

ember maple
#

please go ahead

#

hmm, its a bit stale, may need some love

fiery arrow
#

well, I tried it on python3.9, it worked

fiery arrow
#

I was looking for this thing for a while, but I failed because I googled "python build fixture tree". But then I realized that it's a DAG and not necessarily a tree

frigid basalt
#

Oh wow that looks super cool

bitter wadiBOT
#

Hey @true oar!

It looks like you tried to attach file type(s) that we do not allow (.sln). We currently allow the following file types: .gif, .jpg, .jpeg, .mov, .mp4, .mpg, .png, .mp3, .wav, .ogg, .webm, .webp, .flac, .m4a, .csv, .json.

Feel free to ask in #community-meta if you think this is a mistake.

true oar
#

Why wont the action chains work

#

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains

path = "C:\Programming\chromedriver.exe"

driver = webdriver.Chrome(path)

driver.get("https://orteil.dashnet.org/cookieclicker/")
driver.maximize_window()

try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID,"langSelect-EN"))
)
element.click()

element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.CLASS_NAME, "cc_btn_accept_all"))
)
element.click()

except:
driver.quit()

driver.implicitly_wait(5)

cookie = driver.find_elements_by_id("bigCookie")

actions = ActionChains(driver)
actions.click(cookie)

for i in range(5000):
actions.perform()

hexed cloak
#

And what do you mean by "wont ... work"?

true oar
#

I am trying to make it so that it will click the cookie, on cookie clicker, automatically but it won't click the cookie automatically and I can't seem to figure out why.

#
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains

path = "C:\Programming\chromedriver.exe"

driver = webdriver.Chrome(path)

driver.get("https://orteil.dashnet.org/cookieclicker/%22)
driver.maximize_window()

try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID,"langSelect-EN"))
    )
    element.click()

    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CLASS_NAME, "cc_btn_accept_all"))
    )
    element.click()
except:
    driver.quit()


driver.implicitly_wait(5)

cookie = driver.find_elements_by_id("bigCookie")

actions = ActionChains(driver)
actions.click(cookie)

for i in range(5000):
    actions.perform()```
bright citrus
hard vessel
#

Also. Hi - would anyone have any recommendations for continuous integration validators (such as pylint)? But less... well, critical? I would like to have some leeway with the code I write.

hollow pivot
#

hello

hexed cloak
hexed cloak
cyan flicker
#

I'm losing my mind here. My test passes when sending an empty date array, BUT when it's ran on CLI or in the program, it fails.

        if (date := dates and min([d for d in dates if d is not None])) is not None:
            # Only want the closest date for formula and due date
            log.debug(f"{self.ticket.key} has the following gates and date: {list(zip(gated_labels,dates))}")
            self.dueDate = date.strftime('%Y-%m-%d')
            return self._GatingFormula(key=self.ticket.key, date=date)

The initial if statement is incorrect and always results in True, and an exception is raised on date.strftime as it's a list. Why would pytests be passing when it shouldn't be?

#

I'm an idiot. I have a decorator capturing attribute errors, so the test passes.

cyan flicker
#

So trying to solve the problem above with using caplog. How could I create a caplog fixture that can be used more or less like a decorator or monkeypatch? Instead of writing code in each function like

        for record in caplog.records:
            assert record.levelname not in ['ERROR', 'CRITICAL', 'FATAL']```
kind meadow
#

For that specific example, I would make it a function and call that function in every test that you want.

#

I'm not sure if a fixture can have asserts

#

The docs show something like this though ```py
@pytest.fixture
def window(caplog):
window = create_window()
yield window
for when in ("setup", "call"):
messages = [
x.message for x in caplog.get_records(when) if x.levelno == logging.WARNING
]
if messages:
pytest.fail(
"warning messages encountered during testing: {}".format(messages)
)

hexed cloak
dapper grove
#

Hello everyone.

I have a question regarding pytest and coverage.

I'm differentiating between integration and unittests.

When I want to run unittests I perform pytest tests/unit.

This works as intended but unfortunately the coverage measurement includes modules that are only part of the integration tests.

Has someone an idea how to change this behavior?

Expected outcome:

Unit tests -> Only coverage for unit test modules
Integration tests -> Ony coverage for integration modules

astral raft
#

I feel like I'm missing something small

#

Can I get some help?

#
def test_invalid_response(requests_mock: Mocker):
    resp = requests_mock.get('', status_code=404)
    with pytest.raises(HTTPError):
        invalid_url = ShopifyUrl("")
        assert invalid_url == resp
potent ridge
astral raft
potent ridge
# astral raft I'm getting an assertion error. I would like to make sure that an empty url rais...

I'm not sure what exactly requests_mock is or how it is setup, but what I'd do to debug is the following:

def test_invalid_response(requests_mock: Mocker):
    resp = requests_mock.get('', status_code=404)
    import pdb; pdb.set_trace()
    with pytest.raises(HTTPError):
        invalid_url = ShopifyUrl("")
        assert invalid_url == resp

Then when you run the test (if it is with pytest, run it with either pytest --pdb or even better pytest -s, this latter it will pause in the pdb.set_trace()). When the execution stop there, you can see what is resp and then what is the result of invalid_url

astral raft
potent ridge
slender harness
#

So I came across some videos and articles saying that trying to compare the speed/performance of two implementations of some task should not be done in the same file
I normally would take a given function that I'm trying to time, run 5 to 10 times in a loop, and for each loop measure the start and end times with time.perf_counter()
Then do the same for the other functions I'm testing
Should I be switching to moving the functions to different files and running their tests with the timeit library?

potent ridge
# slender harness So I came across some videos and articles saying that trying to compare the spee...

It might be a good solution as well. Another one that I'm using these last days is this one: https://github.com/joerick/pyinstrument it will give you the whole stacktrace and how much time is being spent in each call

GitHub

๐Ÿšดย Call stack profiler for Python. Shows you why your code is slow! - GitHub - joerick/pyinstrument: ๐Ÿšดย Call stack profiler for Python. Shows you why your code is slow!

#

I used it last week find out some bottlenecks in a test suite and decrease its time from 15min in CI to just 5min

slender harness
#

Oohh that looks amazing, thank you!

tender cedar
#

in pytest, can we modularize conftest.py? We have a large application with tons of fixtures that people end up copying/pasting into the test files they need, heavy violation of what Iโ€™d assume is best practice to write a fixture once and reuse it in many places. Are there any guides/suggestions people have to remedy this problem?

potent ridge
tender cedar
#

Can we have multiple conftest.py in different modules? or is it a single file

potent ridge
# tender cedar Can we have multiple conftest.py in different modules? or is it a single file

yes. Let's say you can have a structure like this for example:

tests
โ”œโ”€โ”€ __init__.py
โ”œโ”€โ”€ conftest.py
โ”œโ”€โ”€ my_project
โ”‚ย ย  โ”œโ”€โ”€ __init__.py
โ”œโ”€โ”€ e2e_tests
โ”‚ย ย  โ””โ”€โ”€ login
    โ”œโ”€โ”€ conftest.py
โ””โ”€โ”€ unit
    โ”œโ”€โ”€ __pycache__
    โ”œโ”€โ”€ conftest.py
    โ”œโ”€โ”€ common_tests
potent ridge
glacial frigate
#

Hello, I'm having difficulty understanding the fundamentals of what unit tests should actually be testing. I feel like at times I'm just re-writing code of the function I'm trying to test

# helpers.py
from typing import Any, Dict, List

def filter_transactions(transactions: List[Dict[str, Any]) -> List:
    """
    Filters the dictionaries for
        * [pay] payment-transaction
        * [axfer] asset-transfer-transaction
    """
    return [trxn for trxn in transactions if trxn["tx_type"] in ("axfer", "pay")]

# test_helpers.py
from .helpers import filter_transactions

def test_filter_transactions():
    transactions = [{"tx_type": "axfer"}, {"tx_type": "pay"}, {"foo": "bar"}]
    filtered_transactions = [trxn for trxn in transactions if trxn["tx_type"] in ("axfer", "pay")]
    
    expected = filter_transactions(transactions)
    
    assert filtered_transactions == expected
     
potent ridge
# glacial frigate Hello, I'm having difficulty understanding the fundamentals of what unit tests s...

So in this case your test is only testing what it's already receiving from the filter_transactions call. A better approach would be something like this:

def test_filter_transactions():
    # Prepare, here you're basically setting up everything you need to run what you want to test
    transactions = [{"tx_type": "axfer"}, {"tx_type": "pay"}, {"foo": "bar"}]

    # Call, here you call the function that you want to test with the data you prepared above
    result = filter_transactions(transactions)
    
    expected = []  # explicitly setting what you think the above call should return
    
    # Assert, finally you will check if the filtered_transaction, which is the result of your function call is equal with what you pre-defined
    assert filtered_transactions == expected
formal panther
bitter wadiBOT
#

:incoming_envelope: :ok_hand: applied mute to @crude badge until <t:1654996927:f> (9 minutes and 59 seconds) (reason: duplicates rule: sent 4 duplicated messages in 10s).

proper wind
#

Why am I getting this error

proper wind
#

class name has to be written that format

#

?

hexed cloak
#

Also pytest tests can't have a constructor

proper wind
#

all test case are in tests

hexed cloak
#

Object.Homepage.HomePage.test_shopItems isn't a valid test name

proper wind
#

i should change the class name first right

hexed cloak
#

Also Object and utilities are very generic package names

proper wind
#

yes

hexed cloak
#

You should pick a top level package name, usually it's the same as your repo name but lowercase and with hyphens replaced with underscore

proper wind
#

ok

hexed cloak
#

So you'd call your repo and project flip-kart and your package would be flip_kart

#

And you'd have flip_kart.utilities and flip_kart.objects

proper wind
#

ok

#

There are two test case in tests one is for login which is working but second one throwing this error

hexed cloak
#

Show the one that's working?

proper wind
#

this is for login

hexed cloak
#

You should avoid inheritance for pytest tests

proper wind
#

thx bro

#

it is working now

hexed cloak
#

And maybe use fixtures instead

proper wind
#

all good

#

the class name is wrong

proper wind
hexed cloak
#

Okay

proper wind
#

Thanks for the help

feral torrent
#

Hi all, just for my understanding of unit tests:
I have a FastAPI application and want to add unit tests. I use also MiniO Storage in this application and now I'm at the point to write Unit tests for all the file handling.
MinIOpy has already unit tests for the library, so what part of my application do I have to test there, and how would I encapsulate this tests?

hexed cloak
#

Then make some requests with the client

feral torrent
# hexed cloak So start with a very simple ```python import pytest import httpx from my_pkg_n...

ok thanks. I started by adding tests for all my CRUD functions. But I always struggle if it is necessary to test basic functions. Because the most struggle here would be to setup a minio test environment to save files.

    def save_file(
        self, bucket: str, filename: str, data: bytes, meta: Dict = None
    ) -> schemas.FileClass:
        """Save byte Stream to s3 Storage

        Args:
            bucket (str): name of the bucket
            filename (str): name of the file
            data (bytes): data stream
            meta (Dict, optional): metatags as dict. Defaults to None.

        Returns:
           FileClass: FileClass Pydantic Schema
        """
        try:
            res = self.s3.put_object(
                bucket,
                filename,
                length=data.getbuffer().nbytes,
                data=data,
                metadata=meta,
            )
            if meta["size"] != "origin":
                size = tuple(map(int, meta["size"].split("-")))
            else:
                size = None
            return schemas.FileClass(
                object_name=res.object_name,
                bucket_name=res.bucket_name,
                version_id=res.version_id,
                max_size=size,
                etag=res.etag,
            )
        except S3Error as exc:
            print("error occurred.", exc)
hexed cloak
#

What happens when you run a simple anyio test with httpx. AsyncClient that covers save_file?

#

You'll probably get an exception of some kind

feral torrent
hexed cloak
#

No it's just how you run tests against an asgi app based on starlette

feral torrent
plush vale
#

I tend to start with tests that are easy to write and provide a lot of coverage, which is often api calls and usually good paths rather than bad paths and edge cases

feral torrent
plush vale
#

yes - amount of code ran by the test

#

i dont think every function needs to be tested in isolation

#

especially in early stages of a project, i find it useful to set up integration tests that e.g. call the api & test the system as a whole, because they will probably tell you if you break something as you develop the internals, but having granular tests for the internal implementation may slow you down if you end up changing things a lot

#

ideally, the api test doesnt have to be changed even if you rewrite the internals completely

#

but tells you when your new implementation doesnt behave correctly

proper wind
#

can we use clear and send_keys both in one xpath

#

like this

#

@hexed cloak

#

i use both indivisually as well but the clear is not working

#

and it is not even throwing any error

hexed cloak
#

I don't know

#

It just hangs?

#

That's a very long xpath - isn't there a css class you can rely on?

proper wind
#

there are multiper class and they don't even have id's

#

it is working xpath is fine

#

but it doesn't clear

bitter wadiBOT
#

:incoming_envelope: :ok_hand: applied mute to @trail sand until <t:1655279558:f> (9 minutes and 59 seconds) (reason: duplicates rule: sent 4 duplicated messages in 10s).

dusty perch
#

Hello everyone,
Hope you're all great

I'm in a bit of a pickle here. I have a Fastapi app for which I am trying to test an endpoint.
That endpoint calls a function that uses an instance that is created in a "on_event("startup")".
Is there a way to mock this instance?

I tried to do it in the .py file where the function is defined and the Class is imported...but does nothing

#

Is this a running in a different thread kind of problem?

dusty perch
#

Well, just solved my own problem ๐Ÿ˜„ it was quite simpler than I thought

hexed cloak
#

The trick is to use the app factory pattern

#

And define your app in `def create_app(database_url=None, etc...):

#

And then pick a default instance if it's not set

proper wind
#

how to handle these two

#

it directly pops-up when i automate

fiery arrow
#

Otherwise, why are you automating it?

proper wind
#

for a project

fiery arrow
#

What kind of project?

proper wind
#

its a project for an company like im trainee in that organisation

proper wind
hexed cloak
proper wind
#

yes

#

but i not able to enter that

#

and can't even able to click in that saved address

hexed cloak
proper wind
#

Hello! Does anyone know how I could assert this code in my test please?

results = ["1234", "4321"]
        for result in results:
            if result:
                import_sports_assets()

the import_sports_assets returns a dict. so I would like to do something like:

assert result[0] == "1234"
hexed cloak
#

You'll probably want to move it into a function so you can test it

split minnow
#

aha okey

#

makes sense

hexed cloak
proper wind
#

Hey, for django testing do you use: built-in django unitest? pytest? django-pytest?
Thank you for your answer

maiden pawn
#

unittest is horrible choice, much less robust

#

pytest alone is not sufficient for launch in django

kind meadow
#

In fairness, that could be due to pytest not being around when Django started.

proper wind
#

@maiden pawn Wonderful thanks

maiden pawn
kind meadow
proper wind
#

@hexed cloak can u help with this why im geting this error or how to resolve it

#

ok i got it

fiery arrow
#

I'm importing my own class called TestCase in a test file. Is there a good way to stop pytest being angry about it?

#

I can import it as MyTestCase or something like that, but that's a bit confusing

#

And is there a way to switch from name-based discovery to something more "rigid"? Like a decorator

plush vale
#

I learnt to stop resisting & accept pytest's automagicality

#

I usually have the test case type defined above the tests that use it, so I find prefixing it with an underscore makes sense

hexed cloak
#

See pytest-relaxed

#

(it's the opposite of what you want)

fiery arrow
#

like this object in the domain of programming quizzes

@attrs.frozen
class TestCase:
    stdin: str
    stdout: str
plush vale
#

ah shit

#

my approach would be to try to find another name that still makes sense

#

i think i'm getting into the habit of using less collide-y names

#

like AppConfig or AppSettings, AppUser, ApiUser if its used by the API service, etc

tranquil wind
#

hi

astral raft
#

Does anyone have any idea how I would go about testing this?

response = requests.get(f"https://www.joules.com/product?id={str(_id)}", timeout=5)
    try:
        response.raise_for_status()
    except requests.exceptions.HTTPError as e:
        return "Error: " + str(e)

particularly this line.

response.raise_for_status()
    except requests.exceptions.HTTPError as e:

I'm using pytest

kind meadow
astral raft
fiery arrow
#

I did something like from my_module import TestCase as MyTestCase

fiery arrow
astral raft
fiery arrow
# astral raft I've never heard of that. Can you elaborate more or give me a link to read?

Basically, instead of this: ```py
class FooApi:
def init(self, api_key):
self._api_key = api_key

def get_foos_count(self, foo_id):
    response = requests.get("https://foo.example.com/foos", params={"foo_id": foo_id})
    return response.json()["count"]

you do this:py
class FooApi:
def init(self, root_url, api_key):
self._root_url = root_url
self._api_key = api_key

def get_foos_count(self, foo_id):
    response = requests.get(f"{self._root_url}/foos", params={"foo_id": foo_id})
    return response.json()["count"]
#

and then for testing, you run a web server that hosts a fake version of the Foo API with the data that you control

#

Or just set up an actual testing/sandbox account on foo.example.com and use it in tests

#

So:

  1. when using requests-mock or responses or something like that, you can set any response code you want, or even raise an exception from requests.get
  2. when using a fake API, you can have it return a predefined error response when it sees some kind of special test data (like foo_id being 666)
  3. when using a sandbox account, you'll need to somehow model the error from the Foo API, so it depends โ„ข๏ธ
kind meadow
#

But who tests the test api :D

fiery arrow
#

well

#

who tests the tests? ๐Ÿ˜‰

kind meadow
#

That's where I give up

fiery arrow
#

I usually give up before getting out of bed, I guess we have different standards

astral raft
#

๐Ÿ˜‚

#

Thanks for the insight @fiery arrow @kind meadow

maiden pawn
frigid basalt
#

This is actually my favourite film of all time

wary lodge
#

I need to test so that two dates are equal but that the time is allowed to be +5 seconds or -5 seconds

so

d1 = 2022-06-22 07:54:30
d2 = 2022-06-22 07:54:35

i want d1 == d2 to be true. if any of the seconds are either 5 seconds more or less than the other.
How would i create a test for that?

royal orbit
fiery arrow
snow hemlock
#

Hey. I have been stuck on this for over 3 hours, someone please assist.
In my Django application, I am trying to test a Form class (ex: MyTestForm).
This form has a ChoiceSelect field, for which the options are populated via a
Customer.objects.all() query.

How do I tell my form instance in my unit test to use the created test Customer database (which has some test records I put in there on setUp() ), instead of querying the actual non-test database?

royal orbit
weary vector
#

Hi! When making functions that receive dataframes as input, should I check in the function itself that the dataframe contains the required columns, or in the unit test?

weary vector
# fiery arrow what do you mean?

Suppose you have a function such as

def total_sales(client_df : pd.DataFrame) -> float:
    return client_df['sales'].sum()

There you need the column 'sales' to exist in the client_df dataframe. Would it be good to have a check of the kind 'sales' in client_df.columns and throw an exception in case that's not true?

frigid basalt
#

That's up to you whether you want to provide that safety

#

Depends on how much you trust the input

#

The code will fail if sales isn't present so I don't see why you'd write a unit test for it?

fiery arrow
#

So if you want this function to fail in a specific way if the input is not right, you should test it

weary vector
#

Thanks @fiery arrow and @frigid basalt for your input!

stark plume
#

How do I mock function with multiple calls but different return values based on input.

trim frost
misty violet
#

In the unittest module, are the unit tests the classes that inherit from TestCase or the methods inside these classes?

import unittest

class MyClass(unittest.TestCase):
  def test_method(self):
    # ....
kind meadow
#

It's the methods

#

The naming in unittest seems confusing. I think the functions are the actual test cases, and the class is.... something? Maybe the class should have been called a test suite instead.

misty violet
#

test cases are called unit tests?

kind meadow
#

No, not necessarily.

#

There could be unit test cases but there could also be e.g. integration test cases

misty violet
#

what is the meaning of test case?

kind meadow
#

It's like the building block of testing. It tests some input and makes assertions on the output.

misty violet
#

So the methods are the test cases (which can be unit, integration and etc)?

kind meadow
#

Right

#

Each method is a test case. A collection of test cases is a test suite.

#

So one could say a method is a unit test. And collectively all the methods are unit tests

#

I don't know why the unittest module decided to call the class a test case. It doesn't make sense to me.

misty violet
kind meadow
#

By default, unittest will only execute the methods whose name starts with test_.

#

And again, they aren't necessarily unit tests. They could be integration tests or another kind of test.

rare atlas
#

or helper methods for test methods

kind meadow
#

The helper methods are not considered to be tests

misty violet
#

oh yes, it's just that I didn't understand the "collectively" part very well

kind meadow
#

Basically, when someone says unit tests (plural), they are referring to a collection of unit test cases i.e. a test suite.

#

Apparently unittest names the class TestCase because an instance of the class only executes a single method. Like, it has this sort of API

def suite():
    suite = unittest.TestSuite()
    suite.addTest(WidgetTestCase('test_default_widget_size'))
    suite.addTest(WidgetTestCase('test_widget_resize'))
    return suite

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(suite())

But usually you rely on the test runner to abstract that away from you.

#

From this perspective, the name make sense. But when looking at a definition of a subclass, it kind of falls apart.

misty violet
#

oh so, for example, would the class be a root test case that checks a unit, and the methods would be small test cases that check pieces of that unit?

kind meadow
#

The way tests are typically organised with unittest is that various test cases for a particular unit will be grouped under the same class.

#

It could be broken up even further e.g. one class for positive tests and another for negative tests. Up to you how you organise it.

misty violet
#

I understood