#unit-testing
1 messages ยท Page 23 of 1
How do I do that. I'm kinda new to testing.
from mock import Mock
stdout = Mock()
?
Is there a good source to learn testing in python?
Which library are you using to make tests?
Here you have some post about mocking in pytest: https://changhsinlee.com/pytest-mock/
As far as I understand the core idea is to create fake objects which allows to test functions in isolated environment
If you don't do that you get integrating test 
So mocking is only for unit tests?
In my opinion not only, you can mock some parts of your application when you make integration tests
In your case you don't need to have working task, you just want to check log method
Here you have how to capture and test stdout https://docs.pytest.org/en/stable/capture.html
Anyone know how to make selenium driver global? I have it so in a gherkin before all function. But when it goes to steps.py it forgets that driver should be in context
thanks, that's a good blog post
Glad to hear it!
Sorry wrong channel
Is there a way to implement unit tests to a script?; How do I unit test methods that are mainly like the following :
def autobump(self):
"""Automatically bumps items for sale."""
to_modify = []
to_bump = []
try:
item_ids = [item['item_id'] for item in self.data['inventory']]
except TypeError:
self.println("Skipping autobump; no owned items")
else:
self.println("Autobump starting..")
for item in self.data['inventory']:
if item['sell_price'] <= item['higher_avg'] and item['profit_forfeited'] == False and item['desperate'] == False:
if item['last_bumped'] == None or (int(str(time.time())[:-8]) - item['last_bumped']) > 86400: #86400 is one day in epoch
to_bump.append(item)
to_modify.append(item)
elif item['sell_price'] >= item['higher_avg'] and item['profit_forfeited'] == False and item['desperate'] == False or item['sell_price'] <= item['higher_avg'] and item['profit_forfeited'] == True and item['desperate'] == False:
self.log(f"Sell price is now over max_sell_price, forfeiting profit.")
item['profit_forfeited'] = True
if (int(str(time.time())[:-8]) - item['last_bumped']) > 259200: ## 259200 represents 3 days in Epoch time
to_bump.append(item)
to_modify.append(item)
self.println("Autobump complete")```
@manic sorrel If you're using pytest it will capture stdout (aka where your println commands are going) and you can assert that certain outputs are what you expect them to be.
Sorry here's a clearer example link
https://docs.pytest.org/en/stable/capture.html#accessing-captured-output-from-a-test-function
Here we are using the capsys fixture in pytest to "capture" print commands. Pytest is powerful, but overwhelming at first. You will sink a ton of time into writing tests until you know the basics, then it'll get easier to write tests.
def test_myoutput(capsys):
print("hello")
sys.stderr.write("world\n")
captured = capsys.readouterr()
assert captured.out == "hello\n"
assert captured.err == "world\n"
print("next")
captured = capsys.readouterr()
assert captured.out == "next\n"
I appreciate your response, So there is no real way to test it except for looking at the print statements?
Thanks, as you said I'll be spending much time learning about this.. Thanks you ๐
Is there a way to create a pretty id for multiple @pytest.mark.parametrize?
@pytest.mark.parametrize("force", [None, True, False])
@pytest.mark.parametrize("limit", [None, 0, 1])
def test_something(force, limit):
pass
In result I can see
test_something[None-None]
test_something[None-True]
test_something[None-False]
test_something[0-None]
...
Is there a way to receive something like test_something[limit=0, force=None]?
In your code, you have conditionals that just print things. If you put in an intermediate variable and returned it from the function in addition to printing it, it might look like this:
def my_fun(input):
...
if condition:
msg = "hello"
...
print(msg)
return msg
then you could test it like:
def test_my_fun():
result = my_fun(INPUT_THAT_MAKES_CONDITION_TRUE)
expected = "hello"
assert result == expected
You could have multiple conditionals that build the message throughout the function and then print it at the very end.
This would let you assert that the message is what you think it is, without having to "capture" stdout. Or you could just keep your print statements as-is and learn how to use the capsys fixture in pytest.
Do I? I can't see the conditionals that just print things that you're referencing, But I understand what you're saying and I really appreciate your answer, thank you!
You could have multiple conditionals that build the message throughout the function and then print it at the very end.```
I've never thought of doing this
I just modified my answer above to be a bit cleaner.
If you decide to build the message over the function, it might look like:
!e
msg = "beginning"
msg += "hello"
print(msg)
@swift bough :white_check_mark: Your eval job has completed with return code 0.
beginninghello
^Except you have to take care of newlines
Oh wow, I didn't know the bot could do that aha
Looks like "!e" has to be at the top of your comment for it to eval I just found out.
I see, that could come in handy
Also if you build the message as a list...
!e
msg = []
msg.append("line1")
msg.append("line2")
print("\n".join(msg))
*fixed
@swift bough :white_check_mark: Your eval job has completed with return code 0.
001 | line1
002 | line2
^ The "001" in eval output is line numbers btw
I was wondering what that was doing there
I don't understand why your code originally returned no output
was it purely a problem with the bot?
I didn't print anything initially. Then I edited and printed the list by accident. Then I edited and printed the proper bit, lol.
I've been struggling for a few days to come up with a good way to test a package like this. Does anyone have any suggestions? Much appreciated.
Mocks?
does anyone have any tips on how to unit test data pipelines? specifically, i use luigi as a DAG orchestrator and it's kind of awkward to set up unit testing through that. note that i specifically want to check "business logic" kind of things, not data validation (i.e. not something like greatexpectations)
Iโm not even sure how to mock it up
huh, this pip install coverage
checks for how much of my code branches is triggered during testing?
so even if I have barely few tests, but they invoke almost all my program parts
it will show a really big percentage?
apperently yeah, cool thing
How does postman automatically generates cookies for a given end-point and how can I recreate it with something like python requests?
I tried response.cookies from requests but it doesn't seem to contain all the cookies like it does in postman's auto generated ones
https://stackoverflow.com/questions/12737740/python-requests-and-persistent-sessions
here looks like an answer
copying
You can easily create a persistent session using:
s = requests.Session()
# After that, continue with your requests as you would:
s.post('https://localhost/login.py', login_data)
# logged in! cookies saved for future requests.
r2 = s.get('https://localhost/profile_data.json', ...)
# cookies sent automatically!
# do whatever, s will keep your cookies intact :slight_smile:
# For more about sessions: https://requests.kennethreitz.org/en/master/user/advanced/#session-objects
@maiden pawn not sure if I'm doing it right cause it doesn't seem to work
I'm not getting an error but I'm suppose to receive a json object and instead it's throwing html file
It works when I do it from postman
I'm passing some cookies in my headers aswell btw
I am unsure where I can test it%
can I PM u?
Yeah, coverage is a good way to make sure your tests are reaching the dark corners of your code. It's another matter to write good tests that reach the dark corners.
I've only just started using Pytest and really paying attention to coverage. It's taken me about as long to cover 50% of my previously-untested code as it took to write the whole thing in the first place.
I think that fixtures are a great way to conceptualize setup/teardown and ensure test independence.
Also if you're getting into Pytest, definitely make use of pytest.mark.parametrize. It took me a bit to wrap my head around, but I think it's a clean/neat way to get into the various branches of a given function.
This isn't quite the space for it but I think y'all are the most likely to be familiar with test tools.
Any strong opinions here on BDD tools? I've been looking at behave and pytest-bdd. At a glance I can see that behave is much more popular but also very stale (last release in 2018, yeesh), and pytest-bdd is much less popular but still maintained. Not much for comparisons on the interwebs.
I'm not sure BDD is appropriate for unit testing, but I plan to use it for end to end black box testing.
how to add costum game activity to bot?
Since we're in #unit-testing - describe desired functionality with tests
Then write obscure text until tests pass
ok I might be getting confused by the name but assert checks if the condition is already asserted right? cause like... it sure doesnt seem like its assigning anything
cause when I assert something, I am declaring it and claiming it as valid right? at least in english
assert(2 + 2 == 5) I see examples like this, is this just an example? cause when would the number 2 ever not be the number 2?
ok I see on stack overflow that it just checks if the expression returns false? So you put things in it that you expect to return true? But why not just put try: Except to catch errors?
How would I write test for a function that only initializes a scheduler:
def file_opened(self, file):
self.task = task.LoopingCall(self.log, file)
self.task.start(self.interval)
Assert is just an elegant way to check stuff. And (at least in the unittest library) there are different ways to assert. For example there is assert_called_once, or assert_called_with that make understanding the code easy.
And I don't see how try/catch is a substitute. The whole point is that we say thar something should be true, and if it's not our test has failed and we want it to crash. Assert is similar to writing
if some_stuff != what_I_expected:
raise Exception
OH
OMFG OK
๐ Just to help people like me:
I assert that such and such should be X. Not that it actually is.
hello
I need help on relative import, if it is the problem
I'm trying to implement pytest here but get No Module named ... error
Can anyone help me on how to fix this? I can't believe this problem takes more time than coding
i fixed it
relative import so bad... need to study on that
Yes, read on documentation in regards to where the default root will hatch - it's related to config or __init__.py. hence may try not having those in tests and it shall go directory upwards. Where crud.py lies. But yeah ultimately docs gives you more options to choose from as well of some posts in blogs about how to make sane project structure that works.
wow. reading
Book by Vladimir Khorikov```
at last
I start to get it
quite good book to reach understanding
captivating
hey, can anyone help me with pytest. need to develop a framework
What is the problem?
i need to develop initial level framework for testing
it should require ssh module ec2 connections
When driving Firefox with Selenium how in the world do you change your user-agent now a days?
Does anyone by any chance know an alternative to vcrpy ( https://github.com/kevin1024/vcrpy )? Looks like I'm trying to do something that seems a bit too "sophisticated" for it ๐ฆ
AWEEEEEEEEEESOME!
Pytest is the best
with pytest-xdist
it makes possible running all tests in multiple core threading
making them super duper fast
speed of tests highly matters
when you realize all pytest features, you understand, unittest sucks
Does factory_boy allow creating multiple related objects?
I have something which uses google translate API, and there's a notebook which gives an example of the module usage.
I'm trying to ensure that all of the example notebooks in the repository are tested - or at least - they're ensured to run without raising any exceptions.
In this instance (something that uses google translate API) I'm unsure what would be done. As I have an env variable GOOGLE_APPLICATION_CREDENTIALS which the code uses - which is a path to a local JSON key ๐ค
how is this typically handled? Please ping me ๐
in github there is mechanism of 'secrets'
you can extract necessary key from there to pipline runner in order for testing ;b
Hrm - we're using gitlab, but i expect there's something similar
Also - the JSON keys are user level, so presumably we'd make a new key for each example (with the minimal amount of requirements?) and read that? Am not too sure
I was wondering how i could fix this unittest output
its giving me the error
'
how do I not access the function directly
https://pypi.org/project/django-stubs/
perhaps here could be some clue
oh yeah, they have it for mail too there
Thanks a lot. I will try.
Hi there!
I have a question about mocking in python.
async def my_production_function():
api_class = get_my_api_class()
data = await api_class.async_call_to_some_endpoint()
# ... some other operations
data = do_stuff_with(data)
return data
Say I need to test my_production_function, how to do go about mocking get_my_api_class and async_call_to_some_endpoint if I don't actually want to initialize (or call) any API ?
I am using pytest-mock.
I have managed to patch get_my_api_class
But I can't find a way to patch that async call to async_call_to_some_endpoint
It finally worked. In the scope of my test function, here is what is did
mock_class = MagicMock(name="ApiClassMock", spec=ApiClass) # this is one of the classes that get_my_api_class can return (can also be the abstract class)
mock_class.async_call_to_some_endpoint = AsyncMock(return_value=5) # data will be 5 when the await returns
mocker.patch('get_my_api_class', return_value=mock_class)
Thanks for your reply.
u a welcome
Does anyone know where I can find how to do a unit test for a login page? I've never used python or done unit testing before so I'm lost and would like something to reference.
Technically that would be an integration test, and you would use something like selenium
For those who need to build integration between teams and have a large amount of fake data for testing, check out https://github.com/ghandic/jsf - it has a seamless integration with FastAPI
WOOOHOOO!
I GOT IT!
I understood what is the sacral point of writing failing test in TDD as first step!
it ensures our brain is thinking how to create structure of the new feature, to be easily testable after that!
well, and to be not forgetting testing
hi, what's the difference between @pytest.mark.xfail and pytest.raises(ExpectedException, func, *args, **kwargs). Both tests will pass if the function returns the expected exception, right?
As far as I know the difference is to mark as xfailed with @pytest.mark.xfail and as passed with pytest.raises(...) 
oh, so say we were looking for a IndexError... pytest.raises() would pass the test, while pytest.mark.xfail would fail it?
pytest.raises would pass if IndexError is raised (otherwise fail), pytest.mark.fail would xfail if IndexError is raised (otherwise xpass)
awesome, thanks for the help
Than more I am reading the book Unit Testing: Principles, Practices, and Patterns by Vladimir Khorikov
Then more I understand, that I don't just learn how to make better tests, but how to write cleaner and better structurized code, which can be easily tested.
How do I write test for a django viewset?
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated, IsManagerOrSuperUser]
filter_class = FoodieFilter
why does assertRaises method fail without using with?
what do you mean by "fail"? i would expect it to do nothing at all if you don't use with
self.assertRaises(ZeroDivisionError, 1/0) (using unitTest.Testcase class) for example outputs this
throw unittest to scrapyard, pytest rulezz
it can do literally everything unittest does, but more and better
i was hoping of having to only rely on what's on the std lib
weird. no idea.
oh
lol
because you actually divided by 0
you wrote 1 / 0
python doesn't capture unevaluated expressions or anything like that
the self.assertRaises never even gets called
it just fails at the 1/0
!e ```python
import unittest
class TestError(unittest.TestCase):
def test_error(self):
self.assertRaises(ZeroDivisionError)
unittest.main()
@pearl cliff :white_check_mark: Your eval job has completed with return code 0.
001 | .
002 | ----------------------------------------------------------------------
003 | Ran 1 test in 0.000s
004 |
005 | OK
@drifting mirage โ๏ธ
What's unit testing
writing automated tests for specific small "units" of code, usually individual functions. people also use the term to refer more generally to writing automated tests for software. automated testing is an important part of software development, but it can be difficult sometimes.
Thanks for the explantion.
Nice.
so I wasn't happy with @pearl cliffs solution, cause it doesn't actually test anything, but this seems to do exactly what you wanted without using the with statement. Notice that I don't actually call the function, cause I don't include the parentheses after it's name. ```py
import unittest
def divide_by_zero():
return 1 / 0
class TestError(unittest.TestCase):
def test_error(self):
self.assertRaises(ZeroDivisionError, divide_by_zero)
unittest.main()
@drifting mirage :white_check_mark: Your eval job has completed with return code 0.
001 | .
002 | ----------------------------------------------------------------------
003 | Ran 1 test in 0.000s
004 |
005 | OK
You know, I was wondering how to do it in one line, without creating a function. I should probably learn what lambdas are, they seem useful
I have seen them before, but they looked a bit scary. But now that I started reading about how they work they don't seem that bad
@drifting mirage :x: Your eval job has completed with return code 1.
001 | <string>:6: SyntaxWarning: 'int' object is not callable; perhaps you missed a comma?
002 | E
003 | ======================================================================
004 | ERROR: test_error (__main__.TestError)
005 | ----------------------------------------------------------------------
006 | Traceback (most recent call last):
007 | File "<string>", line 6, in test_error
008 | File "/usr/local/lib/python3.9/unittest/case.py", line 733, in assertRaises
009 | return context.handle('assertRaises', args, kwargs)
010 | File "/usr/local/lib/python3.9/unittest/case.py", line 201, in handle
011 | callable_obj(*args, **kwargs)
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/qomohaqipa.txt?noredirect
!e
print((lambda a: a + 2)(2))```
@fast niche :white_check_mark: Your eval job has completed with return code 0.
4
cool
hey folks - what is the difference between unit testing and integration testing? also, I'm thinking of setting up github actions for automatic testing (ci) for my django server. currently, just planning on running unit tests on classes, wondering if there's anything i'm missing conceptually
unit testing usually means testing small pieces of code from a single part of the codebase, e.g. a method on a class. conceptually a "unit" probably shouldn't touch too many external systems, ideally zero external systems. integration testing is the opposite, that might be testing a "data flow" between systems, eg. a backend server -> graphql server -> web frontend
i see... so, for integration testing i'll need to emulate a client and make API requests to emulate some sort of "data flow", is that right? I've heard of testing frameworks like jest / cypress for frontend - should they also be a part of the testing? I assume they're more for unit-testing but for JS
thanks for the nice explanation btw ๐
yeah you can use cypress for stuff like that
thats what my company does, anyway
although we dont do a whole lot of that kind of testing
another version of "integration testing" would be within one codebase, where you maybe are using lots of individually-tested pieces together
alright - i'll have a look at jest / cypress. it's just for a personal project, so if I test some sort of line from frontend -> backend that should be good for learning the concept of integration testing.
thanks for the help, much appreciated ๐
Can someone explain to me unit testing? like when to use those?
i mean i watch 10 video in the row
explaining how to check if template is in eg. base.html or smth
but i know it is, and allways will......
Can someone give me Real world project explaining that
@lusty shore I strongly recommend this book (free online):
http://www.obeythetestinggoat.com/
it can feel a bit tedious initially, but stick with it, it goes through a real full application using unit tests, integration tests, and all the other stuff
So I am getting a "ModuleNotFoundError: No module named 'studentdashboard'" error and I'm not quite sure how to fix it. My test file is test_forms.py and I am trying to test the forms.py whose path is studentdashboard.forms, not sure if i explained this part correctly. I'm thought it did the import right but evidently not ๐ฆ
@vivid hill what is the actual file structure?
./ <-- current directory
test_forms.py
studentdashboard/
__init__.py
forms.py
it should look something like this based on what you just described
the right file structure will depend on what else you are doing
on my desktop, folder student dashboard then forms.py with init.py and a seperate folder of tests with test_forms.py
./ <-- current directory
tests/
test_forms.py
studentdashboard/
__init__.py
forms.py
like this?
and how are you running the tests?
yes
command prompt
im not sure if this is right but i do the virtual environment first
and then do python test_forms.py
./
tests/ <-- current directory
test_forms.py
studentdashboard/
__init__.py
forms.py
so your current directory is tests when you run that command?
yes
ok, cd back up to your desktop and run python tests/test_forms.py
that should work
python only knows to look in certain locations for modules. one of those locations is "the current directory"
it does not know to look in other places like "the directory above me"
so instead of doing it as (venv) C:\Users\Bacon\Desktop\Student_Dashboard-master\studentdashboard\tests>, i do (venv) C:\Users\Bacon\Desktop\python tests/test_forms.py ?
in the command prompt
what is your actual file structure
this looks different from what i thought
C:\Users\Bacon\Desktop\
Student_Dashboard-master\
???
what is the ???
i see
cd C:\Users\Bacon\Desktop\Student_Dashboard-master
python studentdashboard\tests\test_forms.py
wait
that command is right but
you have too much stuff in studentdashboard
move all the stuff like readme, requirements, setup, etc. out of that directory
or are they already outside that directory? it is hard to tell
should I make a new folder?
it looks like this
readme, run, app, are all outside of the studentdashboard directory
forms, route, and settings are within the studentdashboard directory
ok, that looks fine
my code was based off Corey Schafer's from his Flask Series Code here
my imports are like so for the forms.py tho
from flask_wtf import FlaskForm
from flask_login import current_user
from wtforms import StringField, PasswordField, SubmitField, BooleanField, SelectField, IntegerField, DateField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError, InputRequired, NumberRange
from studentdashboard.database.models import User, StudentInformation
from studentdashboard.database import db
I've been told that a login page would be more integration testing instead of unit testing
hehe, all tests were passed during development
decided to test in postgres in local machine before deploying
all tests were failed
because max_length constraints were not working in sqlite ;b
Hello, for example i have test called test_username_is_unique
and my form has about 10 fields unique, Sex, birth_date etc...
how should i write test without writing the same fields..
sounds like time for parametrization
available_apps = ['customer', 'payment', 'plan', 'status']
available_models = [Customer, Payment, Plan, Status]
zipped_apps_and_models = [
item for item in zip(available_apps, available_models)
]
@pytest.mark.parametrize("app", available_apps)
def test_url_main(client, one_user_and_payment, app):
"testing main section to choose tables"
resp = client.get(f'/{app}/', follow=True)
assert resp.status_code == 200
@pytest.mark.parametrize("app", available_apps)
def test_url_table(client, one_user_and_payment, app):
"checking farhub table render"
resp = client.get(f'/{app}/{app}/', follow=True)
assert resp.status_code == 200
@pytest.mark.parametrize("app, cls", zipped_apps_and_models)
def test_url_change(client, one_user_and_payment, app, cls):
"checking farhub table renderrender of admin interface to change it"
objects = cls.objects.all()
assert len(objects) != 0
for obj in objects:
resp = client.get(f'/{app}/{app}/{obj.id}/change/', follow=True)
assert resp.status_code == 200
look at those silly 3 tests
which have parametrization
that makes them
3*4 = 12 tests ;b
each test is launched 4 times with different parameters and class objects
pytest is awesome
Hey legends, was wondering if there are any good unittests for dummies guides that youโd recommend?
Previous weekly topic was about testing
#weekly-topic message
You can check #weekly-topic-discussion and maybe you can find something interesting 
trying to find good way to test discord bots
besides testing all logic outside of discord framework
so far have found only this
thinking if I would be too much of a pervert to write my own discord bot testing library
How about this #weekly-topic message ?
You can check how @bitter wadi bot is tested
well, I guess it is time to learn mocks and stabs
@pytest.fixture
def user_data():
return {
"first_name": "first_name",
"last_name": "last_name",
"username": "username",
"email": "email@email.email",
"birth_date": now(),
"sex": "Male",
"password": "Password123",
}
@pytest.fixture
def user_registration_data():
return {
"first_name": "first_name",
"last_name": "last_name",
"username": "username",
"email": "email@email.email",
"birth_date": now(),
"sex": "Male",
"password": "Password123",
"password_confirmation": "Password123",
}
is this good aproach?
pytest is saying that i cant use fixtures in fixtures....
what is wrong with this
!resources You should really stop asking this in random channels, go to #python-discussion , and send code, not a picture. And see what I innked you to
The Resources page on our website contains a list of hand-selected learning resources that we regularly recommend to both beginners and experts.
Add : after range(...)
Anyway, it's wrong channel to ask about it
yep
range(boundary+1): like this bro
is it correct
In your case Boundary is uppercase
But yes, it's range(Boundary + 1):
ok bro thank you very much
Your welcome!
Please, use #python-discussion or offtopic channels to ask about it
!topic
Off-topic channels
There are three off-topic channels:
โข #ot0-psvmโs-eternal-disapproval
โข #ot1-perplexing-regexing
โข #ot2-never-nesterโs-nightmare
Their names change randomly every 24 hours, but you can always find them under the OFF-TOPIC/GENERAL category in the channel list.
Please read our off-topic etiquette before participating in conversations.
Iterating over range(len(...)) is a common approach to accessing each item in an ordered collection.
for i in range(len(my_list)):
do_something(my_list[i])
The pythonic syntax is much simpler, and is guaranteed to produce elements in the same order:
for item in my_list:
do_something(item)
Python has other solutions for cases when the index itself might be needed. To get the element at the same index from two or more lists, use zip. To get both the index and the element at that index, use enumerate.
is this testing bad?
Hey @lusty shore!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
Hey @lusty shore!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
not related to the tests, but
"".join(["0" for i in range(151)])
could be
"0"*150
besides that though, seems pretty reasonable to me
i'm no expert at pytest though
note you have two defs for test_username_max_length btw ๐
Okay I have a question now.
Could someone take a glance at my tests here? Just two short files -- pretty standard stuff
https://github.com/teauxfu/py-hplc/tree/dev/tests
These are unit tests for a package that interfaces with some hardware (HPLC pumps)
I've got tests written for all my methods, and I can run them no problem (in fact, they pass!)
My question is, do you suppose there's a better way I could implement this?
I know most unit tests get run through a CI or similar, but to my knowledge it only makes sense to run these locally.
I know I could mock up the serial connections, but I think that would be essentially fruitless since what I'm really testing is the ability of the pumps to talk with the computer over the serial port. If I write up a script of pump responses to each method/command, all I'd really be testing is my Python syntax...
but those tests are good right?
I mean yeah they seem reasonable, they don't strike me as 'bad'
again, I'm no expert :p I also came here to ask for advice
ok thx
you already separated your code somewhat into lower-level and higher-level "layers", where only the lower-level code actually interacts with the serial protocol. i don't know that you want to mock the entire serial protocol, but when testing the lower-level code you probably should.
also it's a good idea to refactor your code in 1 of 2 ways:
-
the high-level pump interaction code should accept a serial connection as a parameter, so you can easily pass in a mocked/faked serial connection for testing. this is a standard technique.
-
the high-level pump interaction code does not ever interact with a serial connection; instead, it returns a low-level "command" object that can be easily sent over the serial connection by a separate function. this is the "sans-io" technique and it is relatively new and not yet popular (also more complicated).
def serialize(cmd, *args):
...
class PumpController:
def __init__(self, serial_conn):
self.serial_conn = serial_conn
def cmd1(self, val):
self.serial_conn.send(serialize("CMD1", val))
def cmd2(self, val):
self.serial_conn.send(serialize("CMD2", val))
like this i guess
so in regards to 1), am I understanding correctly that you're suggesting
from serial import Serial
from py_hplc import Pump
port = "COM3" # or whatever elese
serial = Serial(port)
pump = Pump(s)
as opposed to passing in the string to init and making the serial connection on my own
hmm okay
yeah i think so
as a convenience you can have the pump create its own serial connection if the user passes None
this way, you can write all your tests for the PumpController by inserting your own serial connection and asserting that the commands being sent are correct
hmm okay, that's fair
I did consider doing something like that at first but opted to accept strings instead since it seemed more convenient
and you can simulate responses with errors etc
I suppose I could type check the args to init at runtime and either store the serial connection, or build one on the fly if they send in a string
yes exactly
or maybe just have an extra kwarg that defaults to None
I was unsure if that would be tacky or not
okay sweet thanks for the feedback
lol
ยฏ_(ใ)_/ยฏ
class BaseViews:
def setup_method(self):
self.url = ""
def test_unauthenticated_view(self, client):
response = client.get(self.url)
assert response.status_code == 200
def test_authenticated_view(self, client):
user = baker.prepare("account.User").__dict__
user_model = get_user_model()
user = user_model.objects.create_user(username=user["username"], password=user["password"], is_active="True")
client.force_login(user)
response = client.get(self.url)
assert response.status_code == 302
@pytest.mark.django_db
class TestRegisterView(BaseViews):
def setup_method(self):
self.url = reverse("account:register")
@pytest.mark.django_db
class TestLoginView(BaseViews):
def setup_method(self):
self.url = reverse("account:login")
what do you think about this test?
yp?^^^^
Makes sense, I don't particularly love using inheritance like that but I see why you did it
If you can make some assertions about the actual content of the view that might be a good idea as well
Ok thx
Hey @proper wind!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
Question about pytest fixtures:
@pytest.fixture
def available_channel():
ch = Channel()
ch.make_available()
return ch
def test_available_channel_can_be_made_pending_by_providing_usernames(available_channel):
available_channel.make_pending(caller='alice', called='bob')
assert available_channel.is_pending()
available_channel is a fixture that creates an available channel (no astonishment yet)
but then I make that channel pending... so it's no longer available, so it's silly to name it available_channel.
How do I proceed?
For me everything is okay. You are waiting for available channel so fixture name is okay. You don't have any scope so as far as I know function scope is default one - each test should take different channel object
right, but
available_channel.is_pending()
``` is nonsense in my context
Hmm... Then you can create class for this
@pytest.fixture
def available_channel():
ch = Channel()
ch.make_available()
return ch
class TestSomeFancyName:
@pytest.fixtrue
def channel(available_channel):
return available_channel
def test_channel_can_be_made_pending_by_providing_usernames(channel):
channel.make_pending(caller='alice', called='bob')
assert channel.is_pending()

I think I found a different approach, because many of my tests relied on a more focused setup
@pytest.fixture
def alice_bob_channel():
channel = Channel()
channel.make_available()
channel.make_pending(caller='alice', called='bob')
return channel
One big sad is that type inference doesn't work with fixtures
smh
so the question is: maybe I can just call a function?
def test_something_important():
ch = alice_bob_channel()
... # boom
pytest tests isolated from each other by default
so it is supposed to be teared down already
if by some miracle, automatic tear down is not working...
huh?
@pytest.fixture
def available_channel():
ch = Channel()
ch.make_available()
yield ch
print('insert your own tear down of channel here')
you can manually destroy channel after the test is finished
I don't need to destroy a channel?
yes, I've seen that you can do teardown as well, if that's what you meant ๐
ah, I see what you mean
requiring a fixture as a fixture invokes the teardown as well
gotcha
makes sense
so when you want to add a teardown, you don't have to change every place that uses the fixture
did you know, you can also use fixtures.... in fixtures? ๐
a chain of fixtures, combined into one single final one
that makes pytest just awesome
Is it definitely go with pytest for testing API built on Django Rest Framework, or stick with default one?
Definitely pytest should be preferred
I have DRF projects too
With pytest my life became much easier
DRF is fully compatible to be tested with pytest
hey all, i have a helper function that is a while True loop. it requests resources from an API until it gets back a response that isn't the max length. i'm trying to write a unit test for it which would request multiple pages but i'm not sure how to mock anything after the first request, any tips?
def fetch_order_products(self, order_id):
page = 1
while True:
try:
order_products_batch = self._request(
self.api.OrderProducts,
self.BIG_COMMERCE_REQUEST_METHOD_ALL,
parentid=order_id,
page=page,
)
order_products_batch = self._ensure_list(order_products_batch)
for product in order_products_batch:
yield product
except UnknownIntegrationLogException:
raise RetryItemException()
if len(order_products_batch) < DEFAULT_FETCH_PRODUCTS:
break
page += 1
thats the helper function, pretty simple.
also open to "that function is stupid" ๐
good afternoon people! so I just created this project here: https://github.com/volundmush/mudtelnet-python
I would like to add unit testing and performance profiling but I'm not sure where to start on either of those topics.
like
where do the tests GO? in a folder next to mudtelnet? in a file? is there some standard command people use to fire off the tests?
mock the _request method with a function that checks the page argument and returns the corresponding page
hmm, i'll give this a shot if i can wrap my head around it, thank you salt rock lamp (i have one on my desk!)
๐
Hi all, can anyone tell me how to replace this typing to calmdown pylint 3.8? Current is: 'Optional[List] = None' is that 'Union[List] | None' or something else? thanks
why does pylint not like Optional[List] being set to None?
it would be equivalent to Union[List, None]
Hey, I'm trying to unittest some code using azure-data-table package. I want to patch the 'TableClient' class, but I'm not sure how to achieve this. I'm new to all the patch/mock of objects.
The TableClient has a class-method, named from_connection_string(connection_string, table_name) which returns an instance of TableClient , and ideally I just wanna test the values used as argument.
@proper wind you want to check that from_connection_string was called with certain arguments?
I've this method, and I want to Mock/patch the return value which is an instance of TableClient, so I can verify that table.table_name was the table_name i parsed to my connect method as an argument , if that makes sense ๐
def connect(self, table_name):
conn_str = os.environ['CONN_STR']
table = TableClient.from_connection_string(
conn_str,
table_name
)
return table
@river pilot
I read your article: https://nedbatchelder.com/blog/200710/flaws_in_coverage_measurement.html
I encountered some of that when testing a small (1600 SLOC) project from scratch. Do you have some thoughts or research on overcoming some of those issues?
In particular I'm interested in the "data structures informing control flow thing". For example, a regular expression is essentially a compact program. But coverage tools doesn't check the paths through a regular expression.
Another example, if I return a higher-order function:
expression = one_of(number, string, conditional)
```... there isn't any way of testing if I'm going through all 3 "branches" here.
I don't have more answers for how to deal with those cases. (And that blog post was 14 years ago!)
IMO, the answer to those coverage concerns is generative testing and fuzzing with something like hypothesis. That is, have a computer think of better tests that actually exercise the input space better
If someone got time and experience with pytest could you consider checking my question #help-croissant? Sorry if I shouldn't be asking this here
#help-croissant message
does anyone have TDD in pdf?
Is there an inbuilt @before method that runs exactly once (at the start of test suite) and never again (like @beforeeach.
Simplified example: Initialize a database. Want to do that once and reuse it in all tests.
I can probably make something of my own with a boolean variable and call it in @beforeeach ๐ค
Hi everyone,
I'm quite new to python unittesting and I'm trying to add a test to a python App. In this app I would like to make sure that the module persist-queue (https://pypi.org/project/persist-queue/) is able to write a message in a FIFO queue based on sqlite database. I don't know exactly where and how to start... Should I use Mock to patch a particular method of persist-queue, how do I have to deal with sqlite ? Any help is very welcome ๐
If you are unit testing, you always mock everything except the method you want to test. The method you are testing, should preferably not depend on other things because then you are not testing a unit anymore.
once I test multiple methods or classes tgoether it's integration testing already, or?
I know there's fixtures for that in pytest, pretty sure unittests have setUp or something along those lines
Testing is not by number of tests, it's by ingredients of the test. Do you test a "unit of code" or multiple units of code, does it include external infrastructure such as GUI or a database
Probably, I made my own. I didn't see anything in a quick google.
Thanks ! I have to admit that testing is still a little bit nebulous, but I got the idea. In my mind mock is used when we have to fake a service
Curretly, the unittest is ran to test that a particular method is able to install an application. In this method i'm using persist-queue, so theire might be no sens to test if persist-queue is working at this point...
Exactly, when you mock, you remove an external dependency because you have essentially hardcoded it. That's why it's still a unit test.
I know of this one, it runs before every test. I would like to run some code before the whole test suite starts and then again at the end.
ok understood, thanks
are you using pytest?
if so, then something like this, I think:
@pytest.fixture(scope="session", autouse=True)
def session_setup():
# setup stuff
yield
# teardown stuff
unittest
Is there something for identifying which test you are in?
Example: If it is executing test 5 of 11, i can use "5" inside the test to uniquely identify some things
I think this is the equivalent in unittest https://stackoverflow.com/questions/8389639/unittest-setup-teardown-for-several-tests
aight.
Hi everyone, please check out this new mock server generator tool that we have developed: https://mockintosh.io
Mocks for microservice environments
It's capable to mock almost every aspects of RESTful APIs and it can even mock asynchronous tasks.
If you are using namespace packages where do you choose to put your tests directory
OpenAPI support?
The management UI automatically generates a Swagger UI out of your configuration file. Let's say you set 8000 port for the management API with:
management:
port: 8000
then http://localhost:8000/oas returns the Open API Specification of the configuration YAML. But if you're asking for OAS to configuration YAML then there is no such thing is possible since OAS does not reveal enough information for mocking.
I see, yeah I was hoping for this:
if you're asking for OAS to configuration YAML then there is no such thing is possible since OAS does not reveal enough information for mocking.
Maybe I will need to investigate further into what your tool does, but if I already have an OAS schema then it's kind of "unsafe" to try and copy it all by hand into another config format
I've realized that we have that in the roadmap actually https://github.com/up9inc/mockintosh/blob/main/docs/Changelog.md#other So it will be there in the upcoming releases.
Ah, that's great. I will seriously have to evaluate this then!
Hopefully you'd also consider supporting OAS 3.1 and not just 3.0
3.1 adoption has been basically nonexistent for some reason
swagger/smartbear seems almost entirely uninterested in supporting it in swaggerhub, swagger editor, etc
likewise with postman
Yes we can consider having the OAS 3.1 support. You can file an issue on GitHub to make it official if you would like to.
OK, I need to get back to work but I will try to remember to post an issue later
Great! Thank you so much for your interest.
(selenium) hey, i want to set a local storage key, but it throws an error (Cannot read property 'setItem' of undefined) Why is window.localStorage undefined??
self.driver.execute_script(
"window.localStorage.setItem(arguments[0], arguments[1]);", key, value)
Here's an example test of uploading a file using SeleniumBase (a Python Selenium framework): https://github.com/seleniumbase/SeleniumBase/blob/master/examples/upload_file_test.py
Hello there, I wrote a TypeDecorator for my Database. No i can't import the Module. And I'm also not sure how to call the Decorator. Does someone know how to fix this?
import unittest
import password
class TestPassword(unittest.TestCase):
def test_password_is_not_none(self):
result = password.TypeDecorator('Test')
self.assertIsNone(result)
what is a TypeDecorator?
I created a decorator for the form field.
class Password(TypeDecorator):
impl = Text
def __init__(self, rounds=12, **kwds):
self.rounds = rounds
super(Password, self).__init__(**kwds)
def process_bind_param(self, value, dialect):
return self._convert(value).hash
def process_result_value(self, value, dialect):
if value is not None:
return PasswordHash(value)
def validator(self, password):
return self._convert(password)
def _convert(self, value):
if isinstance(value, PasswordHash):
return value
elif isinstance(value, str):
return PasswordHash.new(value, self.rounds)
elif value is not None:
raise TypeError(
'cannot convert {} to a Passwordhash'.format(type(value))
)
I do comment the code later ๐
Hi anyone here have experience with the tool called Applitools Eyes?
Hej, me again. Is there a reason why i can't import my modules in my app.py but not in my Test folder?
pycharm?
Might be something with the setup of your directories
VS Code
Don't have much experience with vsc, tell me, does your ide recognize the tests?
And run all of them as expected
I've faced this issue a couple of times on IntelliJ and they were solved by fixing the Project Structure. The test folder was not correctly set or some directory was of the wrong type
I have a feeling you have the same problem
Your imports are working fine (most probably). Something in your setup
I'm working with an venv and my imports working very finr. Just not in that Test folder
Yea, modern ide abstract all that away and give you a button to click which runs all tests. Your ide is not able to make that button for you.
Sorry but that's the best I can do. Your imports are working fine, fix the tests and everything should work.
How can I handle the "leave site" popup in selenium (chrome)?
never had to automate that but have you tried the built-in alert handlers?
Does pytest not support class variables using self?
@wise matrix can you clarify? this might be a "python syntax question" and not a "pytest question"
I have some code to run before test suite and then another bit of code that runs before and after every individual test.
To set some class variable, I used self.
Does not work
class Test:
@pytest.fixture(scope="session", autouse=True)
def setup_before(self):
self.flight_index = 0
class Test:
flight_index = 0
@pytest.fixture(scope="session", autouse=True)
def setup_before(self):
# blah blah
def foo(self):
print(self.flight_index + 1) # prints correct value
but this one does
Pytest complained when I tried to make a __init__, wondering what the best way to set these variables is. It is preferred to have them in a method.
@pearl cliff
this should set an instance variable, not a class variable
although in this case it shouldn't make a difference, at least i think
admittedly im not sure how pytest fixture scoping works
I hope I will get to your level one day, I'm a beginner! Seeing all of this kind of code makes me so motivated to work on my skills @pearl cliff @wise matrix
I think the problem is that there is no instance of Test at the beginning of the session
If you want to setup stuff for the whole session and use classes, I think you'd have to set class variables.
To find the best idiom, it might help if you gave more detail on what your actual use case is
I fixed it temporarily with global to get it to start working
Think of it like this,
Create a database at the start of the test suite (and delete at end).
Before every individual test, prepare the database by cleaning up and at the end of each test log some stuff in a txt file.
Some nuances, each test is run multiple times (parameterized). Since there is one database, it needs to be single threaded. It is a integration test suite
@rustic parcel
@wise matrix Yeah, so you rely on fixture scopes to handle that, and pytest will manage the parameterized tests as appropriate. When I've done that kind of db integration test, I've ended up with a structure something like (from memory here):
# conftest.py in same directory as relevant tests
@pytest.fixture(scope="session")
def database_engine():
# setup real database
engine = create_engine(...) # create connection to database
yield engine
# teardown real database
@pytest.fixture
def database(database_engine):
database_engine.execute(<per-test setup>)
yield database_engine
database_engine.execute(<per-test teardown)
# in test file
def test_something(database):
# use the database here
assert things_are_good
I got everything set up except passing that engine variables around neatly. Does yielding a variable make it available to tests that follow?
the arguments to the yield are like the return value of the fixture, so e.g., inside the database fixture, think of it like pytest called the function database_engine and gave you back the engine
Whatโs the simplest way to unit test a requests.post() api call?
depends on framework. Almost all of them have in built special Test client, which is easiest to make the request call.
in case of not having ability to use it... import requests to local host will work too
How resource starved are github action containers? Trying to migrate from Jenkins, and see a python -m unittest just hanging, and no log output.
my-job:
runs-on: ubuntu-latest
timeout-minutes: 30
?
job.<id>.timeout-minutes sets a timeout for a whole job
job.<id>.steps.timeout-minutes sets a timeout for a single step
So far only 15 minutes in
Nvm, I figured it out
What happens if none of my tests are passing? Is the idea to fix my tests so they pass?
Or fix the main code so they pass?
you need to figure out why they're not passing. if the main code is broken, fix the main code. if the tests are broken, fix the tests. note that if your tests break often, it probably means that you need to redesign or reconsider your tests.
Ok gotcha
So Iโm testing requests api calls and donโt have valid credentials in my tests
ah, that is a hard situation and there isn't a single easy answer
Ok thank you
one option is to use a technique called mocking
Ok
in python, the unittest.mock package gives you the ability to replace any object with a special "mock" object
Ooh ok interesting
this mock object then lets you inspect function calls that were made, attributes that were accessed, etc.
you can even tell the mock to return a certain value if you call it like a function
however mocking can get very complicated
especially if you are trying to mock an external API - how do you confidently mock an API response without mocking the entire API?
perhaps the best strategy is to do as little input/output (i.e. network requests, opening files, etc) inside your code as possible
that is, push i/o to the "edges" of your application when possible
so most of your code should be perfectly testable, because it just operates on data and returns different data
then you only have to worry about using mocking, patching, etc. for the few specific places where you actually perform i/o
this is what a programmer might typically write:
def fetch_tags(article):
tag_ids = article['metadata']['tags']
response = requests.get(
'http://api.example.net/v1/tags',
params={'id': ','.join(tag_ids), 'limit': '5'}
)
data = response.json()
return data['items'][:5]
the problem here is that you are mixing "logic" and "i/o"
how do you test that you fetched the right tag ids? how do you test that you post-processed the data correctly?
one possible solution is to break up your logic into testable pieces:
def get_tag_ids(article):
return article['metadata']['tags']
def process_tags(data):
return data['items'][:5]
def fetch_tags(tag_ids):
response = requests.get(
'http://api.example.net/v1/tags',
params={'id': ','.join(tag_ids), 'limit': '5'}
)
return response.json()
this way, you still have to test the full chain of execution at some point, if only to ensure that the preprocessing and postprocessing functions were still applied. but at least you have 2 standalone tests for the data processing, so you can focus on testing the i/o part separately
https://www.youtube.com/watch?v=ww1UsGZV8fQ
https://www.youtube.com/watch?v=Ldlz4V-UCFw
if you're serious about learning how to deal with mocking and patching, watch both of these presentations, it's worth the time investment.
one more thing:
def fetch_tags_from_article(article):
tag_ids = get_tag_ids(article)
tag_data = fetch_tags(tag_ids)
return process_tags(tag_data)
at some point, somewhere, we need to mix i/o and program logic
I just found this wholesome SO answer/story I wanted to share:
https://stackoverflow.com/a/90021/12340711
@royal wren so to test this fetch_tags_from_article function, one possibility is to mock your own function.
you could skip trying to mock the API entirely by asserting that the internal fetch_tags function was called with certain arguments. then you return specific data back from it that you control, emulating the case where the function executed successfully.
from mymodule import get_tag_ids, fetch_tags_from_article
def test_fetch_tags_from_article():
fake_article = ... # make a fake article object
expected_tag_data = ... # construct the correct expected tag data for this article
with patch('mymodule.fetch_tags', return_value=expected_tag_data) as mock_fetch_tags:
actual_result_data = fetch_tags_from_article(fake_article)
# Assert that fetch_tags() was called with the expected inputs,
# i.e. test that the inputs are identical to the result of
# get_tag_ids(fake_article)
fake_article.assert_called_once_with(get_tag_ids(fake_article))
# Assert that the result was processed as expected, i.e. test
# that the outputs are identical to the result of
# process_tags(expected_tag_data)
assert actual_result_data == process_tags(expected_tag_data)
here, "patch" is replacing the mymodule.fetch_tags function with one of those mock objects
!d g unittest.mock
New in version 3.3.
Source code: Lib/unittest/mock.py
unittest.mock is a library for testing in Python. It allows you to replace parts of your system under test with mock objects and make assertions about how they have been used.
unittest.mock provides a core Mock class removing the need to create a host of stubs throughout your test suite. After performing an action, you can make assertions about which methods / attributes were used and arguments they were called with. You can also specify return values and set needed attributes in the normal way.
the docs are here, but they are not easy to read without additional context
So with using the mock unittesting framework I have this is my test:
But getting ModuleNotFoundError: No module named opentok.requests
Iโm testing a post request
But this works:
@patch(โopentok.OpenTok.muteโ)
If Iโm test sing a post requests inside the mute method is the latter ok or do I need the requests.post ?
@royal wren your issue may be patching the wrong name https://docs.python.org/3/library/unittest.mock.html#where-to-patch its easy to get this wrong (and a good motivator to use mocks sparingly)
I am writing pytests for my API, I have big rather big size of request. Should I separate requests from test_main.py to have less mess in there?
if I were you I would do so
Hey everyone.
I prepared unittest for Python bootcamp . I just wanted to learn how new empoleyee can run pytest without see python test file? I meant I wanted to make it automized at all.
My final goal they will push their code on gitlab and on gitlab they can figyre out their result correct and space/time complexity is okay
read about pytest.fixture
they shorten tests a lot in #arrange sections, they can be used even in chains
plus you could use parametrization
it shortens tests even more... for all remaining sections
anyone have macos ? I want to test my python library
@royal wren is your module called opentok? And you write import requests inside opentok.py?
Hi @pearl cliff I was able to figure out the issue. I wasnโt pulling in the top level folder that held my file.
Anyone ever use the httpretty library?
I have this code from Pypi and wondering why we do two POST requests? One with httpretty.POST and another with just requests.post.
Is it registering a url to be mocked?
Hi @pearl cliff yea, I think so. Httpretty is fairly new, and still learning. Thereโs also not as much documentation.
in that case the first call just looks like it's registering that it needs to inject itself in POST requests
you're not making an extra request
the function is called register_uri
another option is to use a library called vcr, which does actually make the http request, but then caches the result, so that you get the same http response every time, and it doesn't actually hit a server
the advantage there is that you don't need to explicitly do any mocking - you are using real data generated by a real remote server
Thank you, Iโll check out vcr as well.
note that there are several libraries for mocking requests
Ok, Iโm using httpretty for work
So Iโll have to stick with that one but will check out vcr
Have a favorite? I never found one I liked
httmock seemed fine, i try to avoid using them
thanks, i'll take a look. agreed that it is a fine line here between digging yourself out of a hole and digging yourself another one.
sometimes i split my tests like this:
- mock
requests.requestor whatever the lowest level interface to the "outside world" is that i can reasonably mock - use
assert_called_with(or equivalent) to assert that i called it with the right arguments - use fake data for the return value, and proceed with my tests using that fake data
the tradeoff here is that you can end up writing tests that are sensitive to refactoring
but refactoring that changes i/o flow is pretty rare in my experience
I like that approach. I often find it hard to get people to write any tests at all before working through mocking strategies with them. On the other hand, I worry I'm providing tools to shoot ourselves in the foot with mocks everywhere. @pearl cliff
@rustic parcel indeed, that's a problem i'm facing right now. i think it's reasonable to set standards and expect devs to follow them, maybe allowing some % of time for self-study in order to achieve that.
make testing strategy part of project planning and task sizing
and actively discuss with other colleagues
pushing i/o to the edges of your application is also an important strategy imo
@pearl cliff yeah, I am working on that with the team (e.g. we are experimenting with OKRs and a big team one is around testing).
at my org i have been talking about standardizing what is and isn't okay/expected to mock, and i think i also want to bring up standardizing how to do the mocking
I talk about this a lot and demonstrate it a lot, but I don't see as much of it coming back at me. Takes time to get the strategies into the bones I've found
yeah ๐ most frustrating part of software dev imo
fortunately our software is pretty simple and most of the mocking is repetitive boilerplate
not adding too much abstraction or helper functions too early is important too
right now my tests at work are deeply nested mocks, they kind of suck to read and write
but i know that they are not the wrong abstraction
so to test the entire API end-to-end i'm typically stubbing out the auth code (i do auth testing in a separate class), stubbing out at least one database lookup, and stubbing out a database write. i'm transitioning to replacing the latter two with a real database, and just assuming that the local dev has a copy of our database server running locally, which in our case is a valid assumption.
is this the best way? i have no idea
is it working? yes ๐
I've been pretty insistent about not mocking out the db, so for the e2e tests we pull up a docker container with postgres. works... ok. but i like asking postgres to do stuff it is good at so it ends up being part of the logic.
if you ever write this up and are willing to share, i'd be very interested
eh, it's all internal stuff
basically, you should expect to mock A and B using this helper function, you should never mock C because you should be doing it X way, etc.
Siiigh.
It's the question you never want to ask, but know you must, someday.
How to write tests ๐
For a website.
"how" is here a wide topic, might wanna be specific?
Unit Testing: Principles, Practices, and Patterns
by Vladimir khorikov
quite recommending to read
10/10 book to get yourself better in understanding tests
who u, ugly ass mofo
hmm, I need web site tested for Safari browser (or apple web rendering engine in general)
what is the best way to get it (i can run virtual machines if I will find image)
oh yes, I think I was able to find one web site with image for virtual machine
there might be a webkit-based driver for selenium
I could really use some help with unit testing in Flask
Can we combine selenium and pytest for webapps?
that'd be interesting if we had to run it in... say... Travis CI or jenkins
yes you can; pytest is a test runner and selenium is a python library that can be run
we did
absolutely possible
pytest fixtures are nice enough to be used for setup and teardown of it
On ci its OK to use headless selenium or a service container
Hi! I hope you are all doing great. I'm happy to be here, and learn from you and make friends. I'm a newcomer to Python.
I have a question that maybe is not exactly related to unit-testing, but it happened inside a unit-test file. It's about importing functions from other files located in other folders into a test file. I have a main folder with 2 subfolders. One is called GetCounter and the other tests. Inside this GetCounter, there's a __init__.py file. It's an Azure Function that writes to and reads from a CosmosDB database. I want to test a specific function inside this file called getNewCounterValue. In my other folder, the tests folder, I have my test file. I've been trying to import this funtion into this test file, but I always get the same error, that says ImportError: attempted relative import with no known parent package.
How would be the correct way to import that function into this test file? I've tried with from ..GetCounter import getNewCounterValue, and I get the error. I tried with 2 dots, with 3 dots, without any dot... I also tried using sys.path, to no avail.
Thanks in advance. Sorry for the long message.
Can someone explain why i get this error in travis ci and not locally?
The command "poetry run pytest --cov=broccoli tests/" exited with 4.
i see nothing wrong with that command, i'm using the same syntax with other builds and it works
[tool.poetry.dev-dependencies]
pytest = "^6.2.4"
requests = "^2.25.1"
pytest-cov = "^2.12.0"
coveralls = "^3.0.1"
black = "^21.5b1"
i can post the traceback if that helps
Any good books or sites for Python bed
yeah that might help ๐
I sorted it out, turns out the issue was a missing env variable in travis-ci
I have no idea why i got exit code 4 eith pytest however
Theres nothing wrong with the syntax of that command
Took me like half a day to figure it out because of that bad error
exit code 4 doesn't mean it has to be a syntax error
In pytest, the standard convention for passing cmdline parameters to tests is for each option that we add using parser.addoption we have to define a fixture with the same name using @pytest.fixture().
Example:
# In conftest.py:
import pytest
def pytest_addoption(parser):
parser.addoption("--name", action="store")
@pytest.fixture(scope='session')
def name(request):
name_value = request.config.option.name
if name_value is None:
pytest.skip()
return name_value
Now what if I want to parameterize and pass a "variable" number of command line arguments (like *kwargs) to my tests using pytest?
Meaning, whatever cmdline parameters I pass to pytest, even if it's not "fixturised" in conftest, should be accessible to my tests: pytest test.py --param1 val1 --param2 val2
As per documents : https://docs.pytest.org/en/6.2.x/reference.html#_pytest.config.argparsing.Parser.parse_known_and_unknown_args
the pytest argument parser does support parse_known_and_unknown_args but I am not sure how to use this in conftest.
It looks like pytest appends an argument to the end of the parse with nargs="*", and that this value gets set as request.config.args.
src/_pytest/config/__init__.py lines 1323 to 1331
args = self._parser.parse_setoption(
args, self.option, namespace=self.option
)
if not args:
if self.invocation_params.dir == self.rootpath:
args = self.getini("testpaths")
if not args:
args = [str(self.invocation_params.dir)]
self.args = args```
The return of this method is not documented, but you can see it gets the FILE_OR_DIR option and returns that https://github.com/pytest-dev/pytest/blob/main/src/_pytest/config/argparsing.py#L135-L144
The option is added here https://github.com/pytest-dev/pytest/blob/main/src/_pytest/config/argparsing.py#L129
src/_pytest/config/argparsing.py line 129
file_or_dir_arg = optparser.add_argument(FILE_OR_DIR, nargs="*")```
I don't see how parse_known_and_unknown_args can be used since pytest does not give direct access to all the raw arguments passed.
it might not be the relevant topic but it is related to it, I am desperate in need of help xd
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
import time
# SetUP
driver = webdriver.Chrome("C:\Program Files (x86)\chromedriver.exe")
driver.get('http://automationpractice.com/index.php')
actions = ActionChains(driver)
def fooling_around():
target = driver.find_element(By.XPATH("//[@id='homefeatured']/li[3]/div/div[1]/div/a[1]/img"))
actions.move_to_element(target).perform()
driver.find_element(By.XPATH("//[@id='homefeatured']/li[3]/div/div[1]/div/a[2]/span")).click()
fooling_around()
is By.XPATH a function?
well it should be
I can walk you through what I am trying to achieve
I have trying to do this for the last 3 hours
http://automationpractice.com/index.php This is the website and im trying to
click this quick view
it only appears when I hover cursor on it
so this code is supposed to hover cursor on the 3rd pictore on the screen
and when this quick view appears,click it
Hey @proper wind!
It looks like you tried to attach file type(s) that we do not allow (.exe). We currently allow the following file types: .gif, .jpg, .jpeg, .mov, .mp4, .mpg, .png, .mp3, .wav, .ogg, .webm, .webp, .flac, .m4a.
Feel free to ask in #community-meta if you think this is a mistake.
does anyone use the responses library for integration testing? I'v egot a question about it
Hi! Anyone has good resources for Advanced Django unit tests? I mostly find beginner stuff, but I want advanced examples, to get a better feeling at the basis to cover regarding views, forms, models, etc. Thanks!
https://docs.djangoproject.com/en/3.2/intro/tutorial05/
https://docs.djangoproject.com/en/3.2/topics/testing/
https://docs.djangoproject.com/en/3.2/topics/testing/overview/
https://docs.djangoproject.com/en/3.2/topics/testing/tools/
https://docs.djangoproject.com/en/3.2/topics/testing/advanced/
linked in chronology to the requested topic
for a more information about unit testing, highly recommending book: Unit Testing: Principles, Practices, and Patterns by Vladimir Khorikov
hmm, how to check if static file by url path exists if you ara in pytest django ๐ค
Fascinating.
for some reason when I launch pytest for all tests, one test is not passed
but when I launch this specific test, it is passed
I wonder what the hell is wrong with it, not proper isolation between tests perhaps
well, yeah. apperently even if pytest cleaned database between sessions, I should not have requested object with id=1
it got pk=4 due to previous tests.
How do you get PyCharm to run all tests in a project using a hotkey?
Maybe someone here knows but might in try #editors-ides
mocked_requests.assert_called_once_with(
"{backend}{namespace}/path/my_request".format(
backend=BACKEND, namespace=NAMESPACE
),
headers={
"Authorization": "Bearer ACCESS_TOKEN",
"header-id": "<Some mocked object>",
},
json=None,
)
How do I accept any mocked object for header_id?
@proven tendon what do you mean "any mocked object"?
you can't, really. you might have to manually inspect the call_args list
mocked_requests.assert_called_once()
expected_url = "{backend}{namespace}/path/my_request".format(
backend=BACKEND, namespace=NAMESPACE
),
expected_auth_header = {
"Authorization": "Bearer ACCESS_TOKEN"
},
expected_json = None
call_args, call_kwargs = mocked_requests.call_args
self.assertEqual(call_args[0], expected_url)
self.assertTrue(
expected_auth_header.item() <= call_kwargs['headers'].items()
)
self.assertIn('header-id', call_kwargs['headers'].keys())
self.assertEqual(call_kwargs['json'], expected_json)
note that "headers" might be a case-insensitive multi-dict thing and not necessarily a real dict
I want to say words of appreciation to TDD
I have no idea how I lived without it before
hard (or even next to impossible) changes become simple changes.
w
Hi! Probably a noob question, but does it make sense to use the unittest framework to build/run integration tests (in a separate folder/file than the actual unit tests of course)
Still getting used to it xd
awesome library, thanks
shortened time to run tests from 3 minutes to 1 second) in literally almost one line of code.
nothing is more satisfying than running your tests and seeing them all green.
especially during massive refactorization
For pytest, is it better to keep a test module separate from the main package or combine both?
Because I have a src package with several submodules
So I was wonderif if it was more strategical to have src with test next to each other or nah
i think this is common, ./src/ containing python packages, and either ./tests/ containing python packages for testing, or ./tests/ itself being a python package
test vs tests doesn't matter, choose whatever you like
Ok and both folders have to be within a python package? Suppose I have a project with src at the root and test at the root. How can src and test communicate if I don't write an __init__.py file at the root of my project?
@true adder you should make a setup.py for your project and use pip install -e .
or use PYTHONPATH=./src
Does it install your code in your pkgs folder? Might create an exclusive environment for that
im not sure what pkgs is
but yes you should create a venv for every project anyway
The package folder for your Python env
yes, pip installs to the site-packages directory of whatever python installation is running pip
basically, i recommend bootstrapping your project with something like this:
#!/usr/bin/env bash
set -eux -o pipefail
project_name="$1"
project_dir="~/Projects/python/$1"
package_name="$( sed 's/-/_/g' <<< "$project_name" )"
mkdir -p "$project_dir"
mkdir -p "$project_dir/src"
mkdir -p "$project_dir/test"
touch "$project_dir/CHANGELOG.md"
touch "$project_dir/LICENSE.txt"
touch "$project_dir/README.md"
mkdir -p "$project_dir/src/$package_name"
touch "$project_dir/src/$package_name/__init__.py"
mkdir -p "$project_dir/test/test_$package_name"
touch "$project_dir/test/test_$package_name/__init__.py"
python -m venv "$project_dir/.venv"
"$project_dir/.venv/bin/python" -m pip install -U pip
"$project_dir/.venv/bin/pip" install -U setuptools wheel
git -C "$project_dir" init
echo '.venv' >> "$project_dir/.gitignore"
echo '*.py[cdo]' >> "$project_dir/.gitignore"
echo '__pycache__/' >> "$project_dir/.gitignore"
echo "Created new project in: $project_dir"
(i didn't actually test this script, it's meant to be illustrative)
I see. Because I wanted to try with the datadriven cookiecutter
Because they don't have a test package
technically tests can be even in each your sub-module of the project.
At least this is how it is suggested by Django by default
[pytest]
python_files = tests.py test_*.py *_tests.py
usually this is how pytest identifies tests
if he is not.. you can create pytest.ini and put it into it
so... feel free to put your tests into folder tests or having them in each your sub module.
it is only a matter of your preferences ๐ pytest is nice, he will understand both your choices.
and both choices people use... sometimes even together.
I like pretty much having tests.py in my sub modules.
makes usually things easier
I put into global tests only tests which are having some sort of parametrization to test all modules together
What is Unit Testing ?
read book Unit Testing Principles, Practices, and Patterns by Vladimir Khorikov
it explains it pretty much
Trying to get a hold of pytest rn. What can I do to define an init function cleaning everything?
A fixture?
What is unit testing?
wdym by "cleaning"? normally you'd use a fixture in pytest, where in unittest you'd use setUp or setUpClass
@lament ridge https://nedbatchelder.com/text/test3.html
Also see the pins
I did something silly like using a MongoDB Atlas cluster for my mock tests
So I'm using a mock database to store the result of my tests
currently i run a local mongodb database for testing
with the ability to tell my application which db to use
In 99% cases, pytest handles teardown automatically. If not, you can set setup and teardown in one fixture, before and after yield
@versed mortar was seeing your site issue, and what is the differences between unittest and pytest?
intentionally here because this question does not apply just to #dev-contrib
Well, they are different libs. Unittest is a 1st party module, most prominently used in CPython directly. Pytest is a third party package developed by the one and only Ronny (he's active in places around the server).
Unittest is a pretty flexible module, and supports basically any python version you can think of. Pytest offers basically all what unittests does, and has a few nifty features such as parameterize and fixtures (I'd recommend reading up the pytest page about them). What it doesn't implement, you can usually find in plugins such as pytest-mock for mocking.
Pytest supports unittests out of the box, and has guides for migrating a test suite. It only supports 3.6+ but everything <=3.5 is deprecated so...
The pytest page has a list of features, but most of the important things have already been mentioned. https://docs.pytest.org/en/6.2.x/#id1
!pypi unittest
๐ค
like random for example
There are syntactical and semantic differences between pytest & unittest, but those can't easily be summed up, and they aren't as relevant as the high level overview
Or sys, even
ye
Which is objectively better in your opinion and why?
I like pytest because it has the plugin system, and strong fixtures, but you can get by fine with any system really
Also it's not std lib so it can be updated w/out python version updates lmao
Unittest has the obvious advantage of not requiring 3rd party modules, and having long term maintenance from psf
!pypi pytest
Things in the stdlib are usually very stable
I wonder if they have the vanity invite
Hmm I'm not sure if they have a public link. Hey @ember maple sorry to bother ya, but do you have a link for the pytest server? If not, I could generate one.
setup.cfg lines 45 to 53
attrs>=19.2.0
iniconfig
packaging
pluggy>=0.12,<1.0.0a1
py>=1.8.2
toml
atomicwrites>=1.0;sys_platform=="win32"
colorama;sys_platform=="win32"
importlib-metadata>=0.12;python_version<"3.8"```
Copying gh on mobile is hard.
They could easily get it
pytest is much more powerful than unittest
yes, coverage.py's test suite uses pytest
... Does coverage.py's test suite also use itself to check its own coverage?
yes, but it gets complicated ๐
Ah, let's not get into that right now then lol
Is using something like coverage.py a good portion of testing?
Or is that sometimes just icing on the tests?
it doesn't change your tests, it's a way of gauging their effectiveness
So coverage can just be used to run the tests and tells how much of the code ran, with not much extra configuration
And to use tests... What are mock attributes and why do we need mock attributes? When is it not always feasible to have the attribute itself and test with that?
Are you writing a paper on this? hahaha
Mocking generally refers to mimicking the behavior of a unit, without actually using that unit. That can have many uses. One popular example is mocking a network request. Say you are doing something that makes a request to a site and uses the returned response. Well, making a network request can have overhead and sideffects, which you don't want your test to have. You can mock that request to allow you to test the rest of your behavior.
You can also use mocking to do other things. For example, you can use it to test how your code responds to a certain response, or how it handles errors.
No I'm not writing a paper on this I've just never written tests
And CI is so much fun
dw, I'm just pulling your leg
Lol ik
So how are network requests and stuff mocked?
Is one way is to take parts of the program and import them into the tests, then monkey patch them to be mock objects?
If your code looks like: ```py
def request(url):
return response(url)
def my_function():
resp = request("https://docs.python.org/3/library/unittest.mock.html")
if resp.content == "you should really read that link, it has a lot of useful stuff":
...
Mocking could be taking that `request` function, replacing it with a mock object instead, and when your function goes to call `request`, it'll instead call the mock object of the same name
For this example, you'd probably use monkeypatching yeah
Probably through something like unittest.mock.patch
love what you did there
!unshh
โ unsilenced current channel.
wow
pfft
Ok
looks like i was targeted
why were they mentioning everyone?
ยฏ_(ใ)_/ยฏ
!shh
โ silenced current channel for 4 minute(s).
I will remind y'all this channel has a topic
We had a small raid
please ignore it and move on if you don't plan on participating here
!unshh
โ unsilenced current channel.
Hello. Sorry if you were pinged in this channel. We experienced a raid earlier today.
If you wish to discuss the raid please do so in one of the off-topic channels.
wow
some useful stuff got purged ๐ข
noooo
@versed mortar we lost half of our conversation from yesterday
Yep, sorry about that.
I got pinged?
Hi, we had a raid. Please read above.
If you're looking for help with pytest, here's an invite to their server!
mkay
Erm, this invite was previously pinned?
same... I am not even active here ๐
I'm actually surprised the purge command doesn't avoid pins ๐ค
Right. Seems like something that should be pinned, so I'll do that.
Hello. Sorry if you were pinged in this channel. We experienced a raid earlier today.
If you wish to discuss the raid please do so in one of the off-topic channels.
We also lost a few messages from the last day as a result of the clean up, if you're wondering where they went.
@wanton spoke you asked about pytest right?
Yeah
Why did I just get 3 pings here?

yeah same
pros: less boilerplate code, more flexible test layout, nice command line with helpful printouts and lots of configuration options, powerful "fixtures" framework
cons: needs plugins to interact with certain other testing tools and doesn't always work with them
@finite summit @worthy cairn #unit-testing message
Thanks. Sounds like a good difference. I'm considering switching to pytest
overall for most new projects, especially personal projects, pytest is a good option
crisis averted
I've got a project that I've been working on for maybe two months now that I started with unittest and now I have about 105 tests
But pytest seems to have some features that would make testing easier and more effective
it does, i think a lot of devs prefer it
Hypothesis seems like a really awesome tool for testing.
I haven't started using it yet, but I think I'm going to start at some point
i love it @wanton spoke , i use it all the time
ghost ping?
Think so
same here
@proper wind @rocky sorrel #unit-testing message
Sick thanks for clearing it up
ahhh
Awesome. I'll definitely be giving it a try
nice poni
Iโm a huge fan of pytest. Itโs easy to build it into pipelines
Are you specifically referring to ci/cd pipelines?
Yes
Lmao this man typed out everyone's usernames to ping us all
there was a raid, so few ppl got pings ๐
yeah, having a name start with a is dangerous ๐
We had a small raid. Nothing interesting.
(your name is early in the list, that's why you got pinged)
oh
starting with an a? dangerous??? (I got pinged 3 times)
It's not always alphabetical
Why is pytest not scalable?
I can not run a single test without Pytest collecting all of them?
Whoever thought that's a great idea
does this help? https://stackoverflow.com/q/36456920/2954547
I already looked at it, ty for trying
Pytest is not scalable, fundamentally
its a design decision
Pytest first collects data on everything, think of it has collecting meta which includes parameterizing, etc etc everything
whatever you want to do, run one test or thousand, it collects everything
and that's how they give all those wonderful fixtures
I have an expensive test setup process and simply can not afford to run all of those all the time.
because ram overflows during collection
The only solution to this problem is to comment out all other tests
Yes, I would need lazy evaluation (Haskell) to jump around it
whats with the pings
a generator that yields your expensive setup one at a time wouldn't work?
then perhaps this isn't a pytest problem. you'd have the same issue in unittest if setUp() performed expensive operations, no?
i didn't get pinged lol
Couldnโt you move the expensive test setup out of the collection process?
there is a number of ways to avoid the pitfalls you created for yourself with pytest - a key reason why al ltests are colelcted first is that parameterization and setup cost test reordering needs to know all relevant items - a common solution it to simply run multiple pytest calls for parts of the directory tree if you have massive suites - also parameterization can be limited by configruation/options
there are some issues about memory use with >30000 tests- but those take time
What would be an example of such a situation? A fixture that takes five minutes to run and loads 5 GB of data would run right at the beginning and unconditionally, rather than only "on demand" as with unittest?
hmmmmm I could see that if one is using pytest to build a test suite for a database 
What's a really good set of open source Python unit tests to learn from?
I faced the same problem I have from time to time
trying different clients for testing django
client = test.Client()
api_client = APIClient()
resp = api_client.post(
url,
data=data,
format="json",
)
resp = client.get(url, data=data, content_type="application/json")
to make post request
but I get this
ValueError: Content-Type header is "text/html", not "application/json"
hmm, why the hell am I even getting this error
may be Nginx did not transfer headers
oh nvm
<HttpResponseNotFound status_code=404, "text/html">
that's why
I need some command to run os system command from python
which returns return code
import subprocess
def runcommand(cmd):
proc = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
universal_newlines=True,
)
std_out, std_err = proc.communicate()
print(std_out)
print(std_err)
return proc.returncode
nvm, works like a charm
Why not just use subprocess.run?
Depends what you're looking at, I had some fun writing tests for anyio
It's checking for a lot of weird edge cases
oh. that's cool choice. thanks.
my stdout/stderr are shown in a real time now
?
You'd use capture_output=True if you wanted to grab the stdout and stderr like you had in the code
The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle. For more advanced use cases
Habta hier laborrr?
speak English
3 pings in here
Hi, if I would like to unittest code with variables set by os.environ, can I set them same way in test.py? It seems like it would mess my system, according to what I found ๐ค Thanks
if you would use it only as os.environ.get("variable name"), I see nothing wrong here
though, I usually use those variables only in settings/config of my application
it looks a bit weird to me, applicating them directly into tests
it feels a bit wrong to me.
print(f"loading config from {fullpath_filename_config_yaml}")
return yaml.load(open(fullpath_filename_config_yaml), Loader=yaml.SafeLoader)```
``` out_path = os.path.join(TMP_PATH, f"{s.name}.jks")
with open(out_path, 'rb') as cert_f:
new_cert = Secret(f"{s.name}-{format_to}",
s.namespace, SecretType(format_to))
return create_secret(c, new_cert.build_jks(
f"{s.name}-{format_to}", s.namespace, cert_f.read()), update=True)```
code works with files and there could be problem with running it running in threads to not overwrite these env vars.. So I would like to chceck them somehow ๐
is it okay to put `TMP_PATH = 'somepath'` in tests file if it's defined in main.py (in if __name/main block so not imported?) I'm trying to validate.
It feels like skipping a thing I should test also, if its right type ie. Can't wrapt my head around what right approach is..
guys what do you mean by unit testing in python
i dont find any resources in pinned msgs Sorry found it in pinned msgs
ive heard these terms quite a few times but i really did not understand why and how to use it?? need help in this im going through the link provided in pinned msgs, seems like that has pretty much good info for me to get started
Hey. I recently bought Proxies from smartproxy and they got a traffic limit, so I want to minimize my traffic in Firefox. Is there a way to disable like image loading?
- selenium
the pain of not having unit tests is quite high . I heard recently about unit tests to test new code ... seems essential . Looking into it right now , after hours of refactoring yesterday .. and then more hours following that "looking for where the issue stems from" . With a fairly abrupt interruption to everything breaking all at once in between ๐
tribute to named users here , we had a 15-20 minute discussion the other day in python general about unit testing with pytest and coverage.py
https://www.manning.com/books/unit-testing
the book I recommend to all beginners
Unit Testing Principles, Patterns and Practices shows you how to refine your existing unit tests by implementing modern best practices. Youโll learn to spot which tests are performing, which need refactoring, and which need to be deleted entirely! Upgrade your testing suite with new testing styles, good patterns, and reliable automated testing.
Yeah. Industry level programming is impossible without unit testing
Unit testing speeds up programming by several times
and allows to not end up in dead end of not refactorazable code
I see ronny@pytest is here aswell , dropping wisdom . I'll probably scroll through previous messages
Glad to see you on this subject aswell ๐
pytest is good, that's what I am using
I will check it out .
I am not just on this subject.
I am already acolyte of TDD cult)
i see ... ```TDD is a part of agile development where developers write code only when a test fails. A programmer writes a test first, even for the smallest of functionality and runs it to get an obvious fail. Then the programmer writes code only to satisfy the test.
thats where i plan to be ! ๐
i want to be that when i grow up
a little bit weird description
man it's been a frustrating past 12 hours fixing all this code . Its so organized when its written and then stuff breaks and its all a mess
look forward to unit testing
yup.
Writing tests brings you assurance, that your code works
makes you really fast to identify problems
and. well... you wil start writing code that can be easily tested
which sort of restructurizes your code work into much better one
It's very nice . I haven't picked up the subject from only an interest
I heard this from someone else that writes unit tests . I asked how it changed their code
refactoring without unit testing = week / weeks of time
refactoring with unit testing = day / days at best)
speeds up bringing new features as well
And saw that the code was using .. the "assuming feature, as i call it" basically where you describe in a function which type you are expecting to get input into a function , and then you can run a test on whether you're getting the types you're expecting .
That was a conversation that i didn't hear was explicitly about unit testing
moreso about preparing packages for large distribution. pypi
i forget what the technical term is
assert type of variable
sounds like a first step for TDD
I'll get into this book , and unit testing . Wont be uninformed while talking about it for long ๐
yessir
do you have code on github that has unittesting that i can reference? @maiden pawn
true , I see that it's more of an industry standard than beginner/hobbyist programming
HAHAH lol
Mm nah. I don't have currently any public code that I would be proud of.
Learned quite recently, within last months. Having it properly applied only at work in private repos.
Regretfully, not a lot of time left for public projects at the moment.
Too much needs to be learn in free time
Like.. I am having too many gaps in other important fields. Which I can't afford having due to current position.
Ah i see , it also makes sense . I am currently working on the code that is public to "look better" . Also aprpeciate the background , the reference to this book being a recent discovery
I wouldn't say "TDD is an industry standard". It's just a simple concept that you can apply to projects big or small. The concept is more or less to write your tests first.
The reason it is helpful in your case is because when refactoring code you want certain behaviors to hold constant. Enshrine those behaviors in tests prior to making changes.
TDD is not always correct. It is however correct to have unit-tests prior to doing refactors.
ive heard it does take longer to write initially. (and while looking into it more, it's obvious that it does) . I have been writing tests with most of my code already, just havent been utilizing "TDD" to do so . the libraries and so forth. Difficult to make a function that can be extracted to a second test file to run just that piece of code, when it depends on other parts of the program . I see TDD libraries support better ways of doing so
the projects are large , more than 50-100 lines (for a reference) ... and with the plan to add more / learn things in the process .
Yes, mostly wondering where to place the tests and how they'll be incorporated currently . Figuring it out with time i suppose . When extracting a function to a seperate file , can look for a way to do it with pytest or unittest instead
thats how i plan to use it when having an existing project already
usually watch a couple videos from youtube where im familiar with how the developer structures their information . in this case , Corey (Schafer, https://www.youtube.com/watch?v=6tNS--WetLI ) and Socratica (https://www.youtube.com/watch?v=1Lfv5tUGsn8) . Usually when its a long video just clicking through it to see the progression and snippits.
i follow a bunch of others on youtube but i see they havent made a video about this . Could probably do better to search each channel for a relevant video though .
Some people stick a tests folder inside the package, other people do it inside the root repo. "When extracting a function to a separate file" I am not sure what you mean (just importing?) and what relevance it has for the tests, but tests should import from your code. I highly recommend pytest over unittest
100 lines is not large ๐
i meant it to imply that the script is a one-off use . as a generalized statement
You should probably look into how a good python project is structured, especially if you are struggling with things like importing functions across files. Try to look at the source code for a library you're familiar with and try to understand its structure and how things are made available across files
Like "this function was defined in file A and it's being in file B-- how?" etc., then see how that's done in the tests as well.
It's something i haven't fully committed to yet . Moving toward initializing all main classes in the __init__.py file . I'll open a package soon-ish to check it out . I also use other packages as reference .
becomes more and more blocking ๐
I think the code will be a bit easier to reason about if you leave your __init__.py's blank. (Sometimes you stick stuff in there, but often easier to reason about it when it's blank). Just use the __init__.py to indicate that you intend to make the modules and their objects importable.
If you have a folder called foo with an __init__.py, a.py, and b.py, you can import a function called bar, defined inside of a.py, into b.py, by writing from .a import bar.
^ When you write and run your tests however, you may or may not (depending on how you set things up) have the tests inside of the foo/ folder. It might be inside a separate tests/ folder. In a file tests/test_something.py, you would import the test with from foo.a import bar.
Note-- you can also run from foo.a import bar inside b.py. The absolute path works in both cases. The thing that matters is where your terminal is pointing to when you run the code. from foo.a ... is an absolute import, from .a ... is relative.
it's just that within the package, you get the choice of absolute vs relative. If you define tests outside of some package you need to do absolute.
this should help you understand how to bring bits and chunks of code into your tests, regardless of wherever you define the tests.
the issue with running tests , even with an import is that some of the functions i aim to test depend on other objects to have been instanced .
I haven't seen whether unittesting has a solution 100% , i am supposing it does in the integration. (which fixes the problem)
and the issue that has lead to moving the instances to the __init__.py file is that i've seen the instances declared in the __init__.py file are accessible to all other modules , which is what i need . Especially while using sql alchemy sessions i see it's recommended to run this is a main file .. which i see could be the executing file or simply the __init__.py file . I see the init file is not usually referenced this way though
having an issue where a class needs access to another class that is instanced in a different file , without having a sloppy import .. or what i see is weirdly referencing the instance while instancing the class that needs to use it in another file .
It's a rabbit hole that im looking to avoid
@round blade
the issue with running tests , even with an import is that some of the functions i aim to test depend on other objects to have been instanced .
It's possible that this is a problem with your code relying on mutable global state.
this is the code currently. Right now it doesn't have that import error .. but i am looking to add the __init__ file changes soon . And have had the error for some time before this https://github.com/swordysrepo/api_twitch_online
And there are other things i see to refactor.. like the structure of having things in folders
basically your functions should "just work"
if there are things that need to be set up prior to running tests however, use "fixtures"
in this file you can see at line 208 that it references to an instance of db. for example . py def update(self): '''update stream statuses''' # get the current stream queue queue = db.get_operator.queue() # retrieve current status of each stream for i in queue: # if the stream is live var = status(i) if var == True: status_queue.append(i,var) # pass streams to db manager print(status_queue) db.set_operator.status(status_queue) which calls a class inside the database.py file that was instanced in app.py
https://github.com/swordysrepo/api_twitch_online/blob/staging/API_function.py
these 3 files "need to be available" to each other file .. and the classes are initialized
in this case py print(status_queue)
is something i plan to comment out later . It's a "test" to see what the value is while passing it along
sometimes lose track of where the print statements are , so i made a function , in debugging.py for optional print statements. basically when debugging == True then the messages print .
import sys
class checkAlert:
def __init__(self):
self.debug=False
# def alert():
# currentline=
# print(currentline)
# def check(self,msg = None):
# print(f"check/debug {sys._getframe().f_back.f_lineno}: {msg if msg is not None else ''}")
def check(self,msg = None):#this sends when debug is enabled
if self.debug==True:
print(f"check/debug {sys._getframe().f_back.f_lineno}: {msg if msg is not None else ''}")
def check1(msg = None): #this sends whether debug is enabled or not
print(f"check/debug {sys._getframe().f_back.f_lineno}: {msg if msg is not None else ''}")
check = checkAlert()
check.debug = True``` https://github.com/swordysrepo/api_twitch_online/blob/staging/debugging.py
also prints the line that the message is on . So can use it even as check.check() and it will show which line "the program got to" . It's a pypi package i posted .. i forget what the name is .. and whether the install is properly working . And also on github
this is what I mean by mutable global state. You should either have the db object be a globally defined object that's available immediately when the app fires up, or use some sort of connection manager, or something else. This particular pattern is no bueno.
my advice is-- create a string called SQLALCHEMY_DATABASE_URI. Then do something like this:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine(SQLALCHEMY_DATABASE_URI, pool_pre_ping=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Then whenever you need to create a new session, simply do db = SessionLocal()
you have a little more flexibility, in particular this implementation does session pooling and you might want to create some sort of way to close out of sessions when you're done with them.
further looking into fixtures, it does sound like what i am looking for , when running multiple functions (and tests) using the same objects .. or a variety of objects for a variety of tests. listening here .. https://www.youtube.com/watch?v=8mp_1Jt-xHQ starting at 12:12 . and this is the repo shown at the end . https://github.com/sasaporta/pygotham-2017-testing .
but even just doing db = SessionLocal() inside the file at the topmost level indent is going to be better than what you're currently doing IMO.
yeah so then the next step if you take my code would be to do something like this:
# contents of tests/conftest.py
import pytest
from foo import SessionLocal
@pytest.fixture
def db():
db = SessionLocal()
yield db
^ this works to create new sessions for each tests. then when you write a test to make it available you add db into the function signature definition (pytest is weird, it's very metaprogrammey and magical-- but tldr it knows to use db if it's defined in there.)
but in order for that to work you need to make sure your code is built to take in the db objects in the right spots.
i wonder what would the string be declared with?
i wonder whether a session pool creates new sessions each time a function is called .. or whether it just offers the same session to the same function .
Oh I just looked at your code, it's a Flask app!
ignore what I said about SessionLocal etc
use Flask-SQLAlchemy
interesting .. I heard that it doesn't offer much that would make it worth learning outside of regular sql alchemy , and so i haven't integrated it . and learned each seperately together . To be able to use sql alchemy exactly the same in other projects
Flask-SQLAlchemy uses a globally defined object called db that does all the session management for you. You do not need to implement it the way you did. Simply have this inside of a file:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
i have a sample of code that uses flask alchemy that i considered using .. one sec
I'm not sure who told you that.
Flask-SQLAlchemy is mostly the same as regular SQLAlchemy.
but it does a few things-- it uses the Flask config, it is extendible with things like Flask-Migrate, and most conveniently-- and what's tripping you up btw-- it has its own session management
https://github.com/ccall48/gymscore/blob/master/app.py
app = Flask(__name__)
app.config['SECRET_KEY'] = config['secret_key']
# DB Config settings (sqlite for testing)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///gymnastics.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)```
^ yeah something like that.
heard from stack overflow .. subject of whether to integrate with flask sql alchemy . i forget the link
also, the fact that Flask-SQLAlchemy is extendible matters. for pytest there's an extension that works specifically with it that is, IMO, a godsend of a module.
yeahhh , i'll take a better look at it
don't listen to that person, it is considered idiomatic and expected in the Flask ecosystem that you use Flask-SQLAlchemy.
to the extent that I can't imagine connecting to a SQL database in a Flask app any other way. It's just the way you're supposed to do it basically.
I've been eyeing the session management aswell . with making a ton of database calls in the API
session management in base SQLAlchemy is mildly annoying-- by that I mean, it's a solved problem and you can copy+paste code, but it's annoying that you need to copy+paste code.
started with mysql calls .. adn the added postgres with psycong2 .. still kinda crude method of communicating with databases. then added sql alchemy .. see it's time for the flask extension and pytest. Can see the progressions through the commits
Flask-SQLAlchemy solves the problem very nicely by integrating with a few Flask internals involving request contexts.
"too much" copy pasting without sql alchemy imo
are you using mysql or postgres? you have sqlite!
postgres
oh I see what you're saying
i have sqlite? i see maybe just in how it is calling to the postgres database in a url