#unit-testing

1 messages ยท Page 17 of 1

sterile valve
#

so unittest is winning here - it's native library, supported by python devs

#

definately, but as I don't really like junit/xunit style, and never did - I chose pytest. It took some time for me to dive in. But as I'm familiar with other frameworks on other languages it was not a problem in my case

plain siren
#

well good for you but projects have to start somewhere and that looks promising. you don't have to sound condescending

sonic crown
#

is any1 interested in making a quizizz hack?

#

I'm having problem making one, I got the code from github and im trying to fix it but I'm stuck. I will send the code that I fixed and I hope you will help me fix it

sonic crown
sterile valve
#

@plain siren sorry if I sounded condescending - Just.. I've seen too many test frameworks in my life that are long dead now ๐Ÿ˜„ Ofc you can try to use something like this for exploratory or learning. But I would not advice to use on commercial production apps. Of course if it is not a project that should go offline in 2-3 months...

plain siren
#

i didnt ever say it was something i would use on a production application. obviously i'm not going to use brand new repositories in a production environment. that's not the point

sterile valve
#

๐Ÿ‘Œ ok then

night wolf
#

so i am done with writing my first graphql api

#

and i am about to write some tests

#

how should i structure tests

#

i'm planning on using unittest

#

should i make a testcase per mutation? (every mutation has about 3-4 responses)

shut hedge
#

@night wolf That's a difficult question to answer. One thing that you could look at is which test methods share set-up methods so you both only do what's necessary for certain tests and you still stick to the DRY principle. So, group methods together that require the same setUp or setUpClass helpers method and/or look at the logical grouping of tests. At the end, test code is just code as well; try to keep it DRY, simple, and readable.

night wolf
#

alright, thanks for help

#

wish me luck

shut hedge
night wolf
#

is he? oh wow

#

will definitely take a look

#

thanks a lot

night wolf
#

okay so i'm writing tests

#

and i have decided for "testcase per mutation" strategy

#

so i'm having multiple test cases in one file and nosetests and unittests pick up only first test class, how do i fix these?

kind meadow
#

How are you running the tests?

#

I usually do python -m unittest in the root and it will automatically discover all tests

night wolf
#

tried python3 -m unittest app/tests/tests_mutation.py

#

it only finds test for the first test case

#

this is my file

#

i have two testcase classes

#

i'm so confused

#

did some fiddling, nothing seems to work

#

@kind meadow should i just make a a file per mutation?

kind meadow
#

No I mean just type the command exactly how I wrote it (well adding a 3 to python is fine of course)

#

don't specify a file

#

If you do want to run tests for a specific module then try python3 -m unittest app.tests.test_mutation (I am guessing that's the right path)

night wolf
#

it only found 3 tests still

#

i sent a file of my tests, mind giving that a look?

#

also tried nosetests, same thing

kind meadow
#

Oh it seems that in your second test case, your test functions are all nested inside the setup fixture

#

They shouldn't be

night wolf
#

are they?

kind meadow
#

Yes

night wolf
#

frick

#

thanks a lot

#

really appreciate it

kind meadow
#

You're welcome

broken fern
#

Oh, testing!! Huzzah!

#

Anyone doing TDD, Red-Green-Refactor, TCR or any other Test-First style. I would enjoy trading experiences on Kata and Refactoring and such.

marsh raft
#

I've done TDD about twice in my current job, at which I've been four years

broken fern
#

Sounds like you don't do TDD then ๐Ÿ™‚
Do you do Katas?

marsh raft
#

don't even know what those are tbh

#

I refactor occasionally though, fwiw

#

once code is in production I don't refactor much, but while I'm developing something, I do it a lot

broken fern
#

Kata are the exercises that will establish you in the techniques of TDD as Test-First.

marsh raft
#

I may have done some of those. I've done the "python koans", which sound similar; I loved those

broken fern
#

You use the 3 laws

You must write a failing test before you write any production code.
You must not write more of a test than is sufficient to fail, or fail to compile.
You must not write more production code than is sufficient to make the currently failing test pass.
marsh raft
#

yeah I know, and admire those

broken fern
marsh raft
#

actually those are worded a bit more sharply than I'd remembered, but it's an improvement

#

You must not write more of a test than is sufficient to fail is new to me, but seems like a good idea. I'm guilty of violating this pretty often

broken fern
#

Usually I start people off with the FizzBuzz Kata, and move on from there. But I just did the String Calculator one tonight, and really learned that I was not up on my python string functions ๐Ÿ™‚

#

and here is a nice huge collection:

#

Well, if you "work the process" and do kata as regular practice, you will get better at not violating them.

#

The most amazing one was the Prime Factorization one because I would have never come up with the resulting algorithm. But I might say that about the string calculator I just finished as well.

wispy cradle
#

hi!! can someone provide me with some resources to start with testing in python ?? (never done testing before in my life and skipped writing unit test for my assignments too)

#

most basic level to start with ?

night wolf
#

Both are very comperhensive and good for starting

wispy cradle
#

thnx @night wolf

wispy cradle
#

is unit test better or pytest module is better

#

to start with >

#

?

#

i did write some on unittest module but was wondering if pytest was a better option ?

broken fern
#

@wispy cradle I am a big fan not only of unit testing but actual TDD. I have used both Pytest and unittest as well as writing my tests in unittest and using pytest to run them. Personally, I like pytest. It doesn't require any skeleton to setup, just import your module and start writing tests with asserts.

I have very strong opinions about TDD, and if you have even the slightest interest I would be happy to take the time to walk you through the process.

Also, here is a website from the podcast "Test & Code" (which was previously Python Testing) and it is a terrific resource with great links to all sorts of testing products and articles.

wispy cradle
#

thnx @broken fern i would love to learn more about TDD. i will check out the link

#

where is the link?

broken fern
wispy cradle
#

thnx @broken fern

broken fern
#

I am on east coast USA and it is morning now. find me in the evening, and I can actually walk you through process of TDD on a simple kata, and you can build on it from there.

wispy cradle
#

haha im from australia so the timezone is just opposite lol

#

thnx @broken fern

broken fern
#
Medium

Test Driven Development has been around for longer than you probably think, around 2003. Not that far back you say? Well actually TDD isโ€ฆ

Learn from a short example of test-driven development coding session using pytest and implementing the FizzBuzz code Kata.

wispy cradle
#

i use vscode

#

i will check those out tho thnx heaps @broken fern

broken fern
#

The video is fine regadless of which tool you are using, but he is using pycharm. No magic involved, you would just have to figure out which button VSC uses to run your tests. Otherwise it is the same lesson. Personally, I like 2 files one for tests and one for code. but if you are doing a video like this it is easier to do and for the watcher to follow with everything in one file.

#

In general I just run pytest -v in another terminal and that is sufficient for me. But if you are using an IDE they will likely either give you some way to have a terminal inside of it, or specifically recognize and run unit tests. Normally, I just use Vim with 3 windows open, one for a terminal, and one for each file (test_<stuff>.py and <stuff>.py) But that's just me ๐Ÿ™‚

wispy cradle
#

ohh thnx for the info i will try to go through those videos first with all setting up the environment for the TDD and stuffs. thmx @broken fern. u got me pretty hyped wihtout all those resources.

broken fern
#

If you want to see some justification, check these out:
This is a good explanation of "why."
https://www.youtube.com/watch?v=HhwElTL-mdI

This is long, but very good. But it it doesn't use python.
https://www.youtube.com/watch?v=AoIfc5NwRks

"I know I should write some tests, but I can't afford the time. I have to get this feature out the door." That's absolute crap, friends, and if you hear someone say it you should slap them. Yes, tests provide a measure of code reliability at the apparent cost of extra work. ...

โ–ถ Play video

In this talk, Uncle Bob describes the three laws of Test Driven Development, and demonstrates the discipline using the Kotlin language.

0:00 : Introduction into the three laws of Test Driven Development
24:10 : A hand-on demo of Test Driven Development using the Kotlin language
...

โ–ถ Play video
wispy cradle
#

sure thnx heaps bud

#

im watching the videos atm

broken fern
#

Both of those Uncle Bob videos are in the size of an hour, but he is worth it. I tend to listen at 1.7 speed though :).

wispy cradle
#

sure i got heaps of time i just wanna get better

#

at tdd

broken fern
#

You will find that "experienced" programmers who don't do "TDD" will poop on it. And say how bad it is. Don't listen to those people ๐Ÿ™‚ Actually try it and decide based on your experiences. Think of it like sushi. There is an age after which people who haven't eaten sushi, won't bother trying it. It is similar here. The process can feel "silly" at first, until you understand what it does to your code.

wispy cradle
#

i like the fact that it helps with writing low coupling code

broken fern
#

the side effect of that is that you write very "testable" code

wispy cradle
#

well which is a good thing

#

isnt it?

broken fern
#

yes, they go hand in hand. You will appreciate that when you have to add or fix something in code that is tightly coupled.

wispy cradle
#

so far i like the whole idea y u need TDD. i can understand at start it might get too tedious for me.i guess i just need to practice more to get use to it and improve my productivity

broken fern
#

Think of it like baking a cake from a recipe.

#

To learn the process, then to do kata with some regularity will "set" your way of thinking. There are more advanced techniques as you move forward, but they can be a bit much to dump on people before they are ready. Kind of like giving a little kid the 'talk' ... you wait until they start asking those questions ๐Ÿ™‚

wispy cradle
#

sure haha i just started writing tests from today lol Thnx @broken fern for the resources n guidance

broken fern
#

Yes, when you get really comfortable and have done at least 4 different kata... then ask about Zombies

wispy cradle
#

sure thnx

inland sleet
#

In Robotframework, how can I continue onto the next robot file when all tests from one have been executed?

#

Im trying to use the DRY methodology and have a init.robot to open a browser session and then i have a bunch of robot files with tests I want to run against various subdomains of my site, however after the first one executes, the others fail as it can't open the new page I need to run tests against

woeful kelp
#

What lib would you recommend to mock on pytest ?

inland sleet
woeful kelp
#

haha obviously, thks @inland sleet

inland sleet
#

Not trying to be a jerk btw, just figured if you haven't heard of if, it might be a good option

broken fern
rain wigeon
#

test now, regret it later

honest verge
#

s/,/ or/

broken fern
#

Test = good

#

Test early and often! Test first!!!

prisma scaffold
#

is it hard to make an application where i can change color on like mouse or keyboard?

honest verge
#

@prisma scaffold please don't spam random channels with the same question

prisma scaffold
#

@honest verge i was just unsure where this question could be asked

#

my bad

broken fern
#

when using pytest to run your unit tests (or other tests) using --exitfirst (or -x) will stop as soon as a test fails without going through the rest of the test. When working on a programming exercise with a set of unitttests it can keep your screen relevant ๐Ÿ™‚

#

When using python -m unittest from the command line you can add --failfast (or -f)to do the same

broken fern
#

Just because Python calls the library unittest, doesn't mean it can't be also used for integration tests, feature tests, subcutaneous tests or even end-to-end tests.

honest verge
rotund wind
#

Anyone any good at using unittest.mock.patch ?
I thought I knew how to use it but the function I have patched still seems to run everytime I run my tests.
I imported subprocess.call and I have a method that uses call to call notify-send in the command line.
I've (tried to) patch call so I can test it gets called with the right args & also so it won't actually send a notification everytime the tests run. Patch seems to be working but the notifcation pops up every time I run my tests.
I've put the code for the file with the class and the test here: https://pastebin.com/VnPBNa0d

If anyone could help I'd apreciate it, I've been looking at this all day and I can't work out why the notifications are being sent (the tests run fine with the patch).

kind meadow
#

I couldn't reproduce your issue

#

That said, I did have to put the test in a unittest.TestCase class to get the test to even run

rotund wind
#

Thanks for trying @kind meadow, I think I had tunnel vision, I went for a walk and while walking realised that there was another test in another file that wasn't patching the call.
The call didn't exsist when that test got written and the new functionailty didn't break any of the old tests.

I don't have to put it in TestCase on my system; i'm running python -m pytest as my test runner on python 3.8

kind meadow
#

I suspected it may be something like that. And I was using unittest as the runner so that explains the discrepancy.

rotund wind
#

Yeah; I always feel silly when I spend hours on something so obvious. Coding time is never consistant.

tropic maple
#

Hi, im new to Pytest and wondering if there is an appropriate way to monkeypatch a function on first call only?

kind meadow
#

That's a strange thing to need to do. I feel like either you're approaching writing your tests incorrectly or whatever you were testing was not designed to be very testable.

#

What is the context?

tropic maple
#

you could be completely right. i inherited some code and trying to build some tests around it

#

the function i'm trying to test checks for a change in temperature in a while loop

#

normally this will change and return a differential

#

since I'm mocking out the actual call to return a static number, i was hoping to increment the mocked return to a new number the second call

#

to exercise the existing code

#

however, im still pretty new to unit testing so open to any advise on better practice

broken fern
#

Why not put a little logic in the mock

tropic maple
#

like a counter on call?

broken fern
#

Well what do you want to test? Temperature changes or availability of the temperature probe or what

tropic maple
#

that the code to handle the change is doing what it should be

broken fern
#

You could have a list of numbers and each time the gettemp mock is called it returns the next one.

#

But for a unit test you have to be able to test for an expected result

tropic maple
#

i think i could manage that

broken fern
#

So you know how to make a generator with yield right?

tropic maple
#

kinda

#

pytest also has a yield aspect to it though i believe

broken fern
#

Well you have a function with a list or even a file full of values. Each call to it will give you the next one

tropic maple
#

although that might be fixture

#

that's a great idea. simple

broken fern
#

So when you gettemp that is what you return it

#

This way you could have 1 or 10000000โฟ

tropic maple
#

thanks so much. dont know why i couldn't figure that out but it makes sense

broken fern
#

And you can write the test for different states

tropic maple
#

i guess i was thinking too much that pytest had some sort of magic that you could switch it on/off mid-test.

#

that's really great

broken fern
#

Well when you want hooves look for horses not zebras :)

tropic maple
#

lol

#

@broken fern seriously. appreciate it!

#

like i said, im new to unittesting and trying to wrap my head around some of the concepts

#

i'll probably be bugging everyone in here more frequently ๐Ÿ˜„

broken fern
#

There is a guy with a podcast test &code names Brian Okken he is all about the testing and will respond to dm on twitter

#

He has an associated web page that I can't type in but the Strat here link on it is full of all sorts of useful stuff for Python testing and testing in general

halcyon zodiac
#

Why can't you type a web page?

broken fern
#

There it is

#

@halcyon zodiac because I am on my phone and can't type well on it :)

tropic maple
#

ha thanks ๐Ÿ™‚ i have started listening to Brian Okken

broken fern
#

But I can cut and paste

tropic maple
#

i came to python from another language and I must say, i'm VERY impressed by how awesome the community is

broken fern
#

Well if you are into TDD we can have a deep chat on that. But any testing is better than no testing

#

What language is that?

tropic maple
#

C

#

and objective-C

broken fern
#

well I've been doing C/C++ since 1989

#

never really messed with ObjectiveC

tropic maple
#

youre better off ๐Ÿ™‚

tropic maple
#

@broken fern if i have a generator that yields a list item, when i call that function (generator) I get a generator object back

#

without changing any of the current logic in the function under test, how would i call that monkeypatch generator and get __next__

broken fern
#

not sure I follow

#

I thought we were discussing returning a temperature.

#
def temp_gen():
  for x in [99]*10 + [88] + [99]*10:
    yield x

gen = temp_gen()
try:
   while true:
     temp = next(gen)
except StopIteration:
   pass

Something like this

#

@tropic maple boo!

tropic maple
#

oh great ๐Ÿ™‚ thank you

broken fern
#

Hope it works.

kind meadow
#

I have this situation

# foo_module.py
from x import y


class Foo:
    def bar(self):
        return y.z


# test.py
from foo_module import Foo

How would I patch the z attribute of foo_module.y? As you can see, my test doesn't have the module foo_module, only the class Foo.

#

Do I have to change the test's import so that I can patch the module too?

halcyon zodiac
#

You can import y from foo_module, can't you?

kind meadow
#

Yes, I can. Turns out the issue was incorrect order for the patch decorator

#

In my test I also have from x import y, and patching that works too. Not sure why. I don't really understand how Python looks up objects.

#

Is it cause modules are really imported only once? And other imports just re-use it?

#

Cause y is a module

#

So question now is why does patching a_module.AClass work within the test when that import is separate from the one done inside foo_module

unkempt aurora
#

can someone correct me if im wrong but if your trying to make a software with python would you use Tkinter ? please @ me so i dont forget

tight geyser
#

@unkempt aurora it depends, what are you making
also this is not #unit-testing related

unkempt aurora
#

Sorry

finite bay
#

Im looking for a quick way to time how long a program takes to run and compare it to another - seems to be alot of options out there so any suggestions?

broken fern
#

like this?

#

or if you use ipython they have some magic %timeit

honest verge
#

there's also the time command in linux if you're on a Mac/Linux computer and work with CLI apps. See man time.

ashen whale
#

Hi there, having issues with patching. How can I patch or mock a class that is both defined and instantiated in the same file? Seems like patching only works for imports. Thanks! (unittest)

kind meadow
#

@ashen whale Sounds like you need to use unittest.mock.patch.object(module_name, "class_name", ...)

ashen whale
#

thanks @kind meadow , doesn't seem to have any effect but will keep trying different things

kind meadow
#

When does the class get instantiated? If it's as soon as the module is imported, then that's likely the problem.

ashen whale
#

yeah my thoughts as well...basically it's like

Class A:
    pass

ClassA()
#

I tried:

patch.object(path.to.module, 'A')
kind meadow
#

Right. The code executes at import time, so by the time your patch is called, it's too late since the class has already been instantiated.

ashen whale
#

exactly

#

(did print statements to confirm ๐Ÿ™‚ )

kind meadow
#

You may not like this answer but the fix is to just not instantiate it at import time.

ashen whale
#

so i may need to instantiate this in another way that is not file level

#

sounds like we are on the same page

kind meadow
#

You can put it in a function. Depending on your use case, you could either have whoever imports the code call the function or you could call it in the same module but use if __name__ == "__main__" so that the code only executes when the module is not imported.

ashen whale
#

sounds good, ill think of the best use case here. Appreciate the help!

zealous pollen
#

Does emteria os work on Raspberry PI 4 now?

stone flare
#

I have a web scraper that is hanging on certain sites. What is the best way to try and find what is causing it to hang?

fiery cove
#

print the answer's body

#

It's probably js-generated pages

indigo forge
#

Anyone got any experience getting boto3.resources to work in the local stack for test automation?

#

I'm having trouble getting my tests to work in the local stack becausue i'm calling the resource (would calling the client make any difference?) to my understanding it will still not work

violet birch
#

is there a way to get the name of the unittest to be run within setUp of a unittest.TestCase ?

#

basically during setup i create (currently randomly) named sqlite.db file and i want to name them after the test

kind meadow
#

Why not create a single database and use transaction control instead?

#

But no, I don't think it's possible to get the current tests name within those fixtures.

marsh raft
#

@violet birch If you use pytest, it's possible

#
def test_wat(request):
    print(request._pyfuncitem.name)
    5/0

# python3 -m pytest wat.py
# ==================================================== test session starts =====================================================
# platform darwin -- Python 3.8.1, pytest-5.3.2, py-1.8.1, pluggy-0.13.1
# rootdir: /private/tmp
# collected 1 item

# wat.py F                                                                                                               [100%]

# ========================================================== FAILURES ==========================================================
# __________________________________________________________ test_wat __________________________________________________________

# request = <FixtureRequest for <Function test_wat>>

#     def test_wat(request):
#         print(request._pyfuncitem.name)
# >       5/0
# E       ZeroDivisionError: division by zero

# wat.py:3: ZeroDivisionError
# ---------------------------------------------------- Captured stdout call ----------------------------------------------------
# test_wat
# ===================================================== 1 failed in 0.09s ======================================================
eager igloo
#

hey all - I'm having a really hard time getting celery to work with pytest in a flask app and I was wondering if there's anyone I could share some thoughts with about it. When I run a test that uses endpoints that involve celery, the test will be irresponsive with no real traceback or details. when I ctrl-c out of the test, it looks like its not getting the proper conf details such as the broker for some reason.

torn mirage
#

@shut hedge you mentioned I could ping you if I ran into some trouble with the tests can move to dev contrib if it's more fitting there, mostly playing around with how to do it in the future but ran into a small problem with the command I'm testing...

    @commands.command(aliases=("hush",))
    async def silence(
            self,
            ctx: Context,
            duration: HushDurationConverter = 10,
            channel: TextChannelConverter = None
    ) -> None:
        """docstring"""
        channel = channel or ctx.channel

        if not await self._silence(channel, persistent=(duration is None), duration=duration):
            await ctx.send(f"{Emojis.cross_mark} {channel.mention} is already silenced.")
            return
        if duration is None:
            await ctx.send(f"{Emojis.check_mark} Channel {channel.mention} silenced indefinitely.")
            return

        await ctx.send(f"{Emojis.check_mark} {channel.mention} silenced for {duration} minute(s).")
        await asyncio.sleep(duration*60)
        await self.unsilence(ctx, channel)

Got from the other cogs how to test the send through extracting its call args but how should the internal command it calls be handled? Just let it pass in this test and then test properly in others?
The second command coro used there also messes it up because of the self; how should that be dealt with? Or just looking at it now should that be invoked from ctx? Not really sure on the differences there

shut hedge
#

Do you mean self._silence(channel, persistent=(duration is None), duration=duration)?

#

If so, I'd test it separately, since it's a clear, seperate "unit" you can test independently

#

That means you can mock it here just to make sure you test every branch of execution within this coroutine

torn mirage
#

Yep for the internal
The unsilence that goes after a sleep delay... should that be an invoke? The tests run without an issue if it is one as the duration can be a float when passed directly

#

Also, how many test cases should there be for stuff? test each execution branch once or get some edge cases etc. there too even when the result is the same?

shut hedge
#

I wouldn't overdo the number of test cases, so a combination of testing each branch + things like very obvious boundary conditions that could make a difference.

#

I don't see many very tricky boundary conditions here (does HushDurationConverter already make sure that duration is non-negative?)

torn mirage
#

yes, it regex matches it for a \d[mM] like pattern

shut hedge
#

Right, yeah. So that one would be good to test with boundary conditions like "what happens with a negative duration" (regex doesn't match, but we should at least have that codified in a test so that if a change breaks that, it becomes obvious)

#

but that's not this command coroutine

#

From the perspective of this function, we can assume that the input is supplied properly by the converter

torn mirage
#

Was more curious because of the HushDurationConverter test conditions actually with the regex it involves... had a bunch but reduced it to 2 cases before commiting

#

Alright so here I would mock the _silence to return the bool I need and then test what was sent to ctx in this command

shut hedge
#

Sounds good

torn mirage
#

bit out of scope for here (can move to dpy) but what about the unsilence? It shifts the args and ctx is passed as self etc. when it's as above resuling in an error when it tries to access a channel

shut hedge
#

Is unsilence another command decorated method?

torn mirage
#

yep

shut hedge
#

I think you'd normally use the invoke method of Context for that, right?

#

!docs get discord.ext.commands.Context.invoke

bitter wadiBOT
#
await invoke(*args, **kwargs)```
This function is a [*coroutine*](https://docs.python.org/3/library/asyncio-task.html#coroutine).

Calls a command with the arguments given.

This is useful if you want to just call the callback that a [`Command`](#discord.ext.commands.Command "discord.ext.commands.Command") holds internally.

Note

This does not handle converters, checks, cooldowns, pre-invoke, or after-invoke hooks in any matter. It calls the internal callback directly as-if it was a regular function.

You must take care in passing the proper arguments when using this function.

Warning

The first parameter passed **must** be the command being invoked.

Parameters  โ€ข **command** ([`Command`](#discord.ext.commands.Command "discord.ext.commands.Command")) โ€“ A command or subclass of a command that is going to be called.

โ€ข ***args** โ€“ The arguments to to use.

โ€ข ****kwargs** โ€“ The keyword arguments to use.
shut hedge
#

Anyway, it's late here. I'll check back tomorrow morning.

torn mirage
#

Thanks for the help

shut hedge
#

no problem at all. thanks for working on the issue.

torn mirage
#

Say I have a test that has no special args, just checks a thing once; should a subtest be used there?

marsh raft
#

doubt it

#

even though I'm not 100% sure what you're talking about

#

"Keep It Simple, Stupid" is pretty good advice; a "subtest" sounds less simple than just "a plain old test"

kind meadow
#

A subtest is used when it needs to repeat assertions with different parameters.

#

It doesn't sound like you need one but your explanation wasn't very clear.

torn mirage
#

With a coro like this, what should be tested there? Checking logging messages seems a bit too much, the return bool is the same for different branches so that doesn't seem like the best way. Or would checking the bool while also mocking the _notifier.start to check if it was called be good? Just can't think of anything that doesn't sound a bit too complex

    async def _silence(self, channel: TextChannel, persistent: bool, duration: Optional[int]) -> bool:
        if channel.overwrites_for(self._verified_role).send_messages is False:
            log.debug(f"Tried to silence channel #{channel} ({channel.id}) but the channel was already silenced.")
            return False
        await channel.set_permissions(self._verified_role, overwrite=PermissionOverwrite(send_messages=False))
        if persistent:
            log.debug(f"Silenced #{channel} ({channel.id}) indefinitely.")
            self.loop_alert_channels.add(FirstHash(channel, self._notifier.current_loop))
            with suppress(RuntimeError):
                self._notifier.start()
            return True

        log.debug(f"Silenced #{channel} ({channel.id}) for {duration} minute(s).")
        return True
kind meadow
#

It'd be a bit easier if the code under persistent was a separate function

#

Definitely don't need to check the logs.

#

Well, the code for persistent doesn't seem to be dependent on anything else the function does, so it could be written as a separate test rather than a subtest

#

You could have 3 separate tests:

  1. Return false if send_messages permission is False. If you feel it's necessary you could also assert set_permissions isn't called.
  2. set_permissions gets called and true is returned
  3. If persistent is True, test adding to the set and that start is called. Could use subtests to assert the aforementioned will not happen when persistent is False.
torn mirage
#

the notifier handling could be moved to a second class now that you mention it as it doesn't really interact with other parts, thanks

torn mirage
#

How do the test mocks work? Wondering how the send_messages from the first test leak to the second one when I have a different mock object. Are they reused if set?

    def test_silence_private_for_false(self):
        """Test whether `_silence` does not set permissions and returns `False` in an already silenced channel"""
        channel = Mock()
        overwrites_for_mock = Mock
        overwrites_for_mock.send_messages = False
        channel.overwrites_for = overwrites_for_mock
        self.assertFalse(asyncio.run(self.cog._silence(channel, True, None)))
        channel.set_permissions.assert_not_called()

    def test_silence_private_silenced_channel(self):
        """TODO +NAME"""
        channel = MockTextChannel()
        print(channel.overwrites_for.send_messages)
        self.assertTrue(asyncio.run(self.cog._silence(channel, False, None)))
        channel.set_permissions.assert_called_once()
kind meadow
#

They are not re-used if a different mock instance is being created for each of the tests.

#

Have you actually confirmed that a mock is being re-used in a different test or is that just an assumption?

torn mirage
#

the False is carried over from the first test to the ones that run after it, it's for the above function

#

alone they all run fine, but together the first check is always true

kind meadow
#

I see. overwrites_for_mock is the Mock type rather than an instance of a Mock

#

So yes, attributes set on a type do persist.

#

You probably meant to use an instance there.

torn mirage
#

Oh right, they're all Mock's. How should I go around mocking the send_messages here? Making it an instance makes the send_messages attrib a mock

kind meadow
#

Like this ```py
perm_overwrite = discord.PermissionOverwrite(send_messages=False)
channel = Mock(overwrites_for=Mock(return_value=perm_overwrite))

#

The PermissionOverwrite doesn't really need to be mocked since it's a simple class

#

But you could if you wanted to, just by swapping out discord.PermissionOverwrite with Mock

#

Can also be done this way since overwrites_for should already be an existing Mock: ```py
perm_overwrite = Mock(send_messages=False)
channel = Mock()
channel.overwrites_for.return_value = perm_overwrite

torn mirage
#

Ah, missed that bit about setting attributes through kwargs in the docstring. Thanks again

#

Was overcomplicating it in my mind and googling didn't yield results

#

Doing this for a patch, is there a better way that doesn't involve a partial?

        with mock.patch(
                "bot.cogs.moderation.silence.Silence._unsilence",
                new_callable=partial(mock.AsyncMock, return_value=True)
        ):

for an awaited coro

kind meadow
#

Wouldn't just patch('...', return_value=True) work?

#

Also, patch.object may be more appropriate than patch.

kind meadow
#

How could something in __main__.py be patched? ๐Ÿค”

torn mirage
#

can you import it?

kind meadow
#

Yes, I can import it but not patch it

#

The patcher can't figure out where it is

torn mirage
#

it seems to work for me if I understood correctly, got an example?

from unittest import mock
import package.__main__

with mock.patch("package.__main__.func", return_value=10):
    print(package.__main__.func())

#######################
10
kind meadow
#

What if you don't import it before patching?

#

Does patch require things to already be imported?

#

Cause the whole reason I need to patch it is to prevent code from executing when importing it

#

I may have to do if __name__ == "__main__" inside __main__.py instead

#

It probably does need to be imported, it wouldn't make sense to be able to patch without importing

torn mirage
#

the patch works without me importing it myself, but it gets imported somewhere along the way

#

and can't change main itself

#

Do you just need to keep it from running?

kind meadow
#

I need to prevent the bot from starting

#

I this this is the best way ```py
if name == "main":
bot.run(BotConfig.token)

torn mirage
#

this seems to work

with mock.patch("package.__main__", create=True):
    import package
kind meadow
#

Well I need to access the bot instance it creates so I can't just mock the entire module

torn mirage
#

Does seem to need an import before accessing anything beyond main in the dotted path

kind meadow
#

Thanks.

#

Wasn't really thinking. Of course it needs to be imported...

torn mirage
#

Feels like this should be somehow separated as the test seems a bit complex but it tests one branch

    def test_unsilence_private_unsilenced_channel(self):
        """TODO"""
        perm_overwrite = MagicMock(send_messages=False)
        channel = MockTextChannel(overwrites_for=Mock(return_value=perm_overwrite))
        with mock.patch.object(self.cog, "notifier", create=True), \
             mock.patch.object(self.cog, "muted_channels", create=True):  # noqa E127
            self.assertTrue(asyncio.run(self.cog._unsilence(channel)))
            channel.set_permissions.assert_called_once()
            self.assertTrue(channel.set_permissions.call_args.kwargs['overwrite'].send_messages)
            self.cog.notifier.remove_channel.assert_called_once_with(channel)
            self.cog.muted_channels.remove.assert_called_once_with(channel)

Does this look fine or should it be in 2-3 tests? It feels like they'd be a bit too short (if that makes sense) when just checking the notifier and muted_channels were called separately, but the patches together also aren't nicest

kind meadow
#

Hard to say without more context.

torn mirage
#

for this

            await channel.set_permissions(
                self._verified_role,
                overwrite=PermissionOverwrite(**dict(current_overwrite, send_messages=True))
            )
            log.debug(f"Unsilenced channel #{channel} ({channel.id}).")
            self.notifier.remove_channel(channel)
            with suppress(KeyError):
                self.muted_channels.remove(channel)
            return True
kind meadow
#

I don't know enough about the code but it seems like these three things are independent, so they could be in separate tests

#

As in, removing a channel doesn't rely on the permissions to have been set first (unless you need/want to test the order of execution)

#

It's fine to have small tests. That's what units are after all

torn mirage
#

ah sorry I cut off the first line, which is an if that the permissions are False on send_messages

#

so when that passes the above is executed

kind meadow
#

Yeah I think it's still OK to make them separate.

torn mirage
#

How do you think it'd be best, 1 unit each for the overwrite, notifier and muted_channels?

kind meadow
#

Yeah, that sounds good.

#

Some others things: 1. a decorator may look nicer than a context manager for the patches 2. Don't use asyncio.run, you can subclass a special TestCase (see other tests for exact name) which supports async def tests, meaning you could just await inside them.

#

If you created the cog in the setup fixture, then it'd be recreated for each tests thus you could overwrite attributes directly with mocks rather than patching. But I don't know the best practices on that.

torn mirage
#

Oh I think I saw the async testcase somewhere, and the completely forgot about it; thanks.

#

Are the decorator patches something that's preferred overall?

kind meadow
#

I'm not 100% on their differences but I think it's just a stylistic thing in this case

#

Using a decorator I believe required the mock to be added as a param for the function, where as it can be omitted when using a context manager.

#

I prefer less nesting so I usually use the decorators

#

Especially if there were going to be multiple patches like that (though I recall a patch.multiple exists but I've never used it)

torn mirage
#

I'm at 98% coverage with 2 line_num->exit not covered on ifs.
Are those for when the condition is not met or something different? Adding a test case worked on one method but can't get it for those two
For example this if (whole func body)

        if await self._unsilence(ctx.channel):
            await ctx.send(f"{Emojis.check_mark} unsilenced current channel.")

has partial from

    async def test_unsilence_sent_correct_discord_message(self):
        """Check if proper message was sent to `alert_chanel`."""
        with mock.patch.object(self.cog, "_unsilence", return_value=True):
            await self.cog.unsilence.callback(self.cog, self.ctx)
            self.ctx.send.assert_called_once_with(f"{Emojis.check_mark} unsilenced current channel.")

    async def test_unsilence_skipped_sent_on_non_silenced(self):
        """test partial"""
        with mock.patch.object(self.cog, "_unsilence", return_value=False):
            self.ctx.send.assert_not_called()
obsidian mortar
#

I was wondering if someone could take a minute or two to look over my first set of tests I've written? I'm not 100% sure I'm headed down the right path - I've taken each function in a single file and have written a test for valid and invalid values.

kind meadow
#

For the first test, test_get_team_id, you should split it up into three tests

#

One for a valid team name, one for an invalid team name, and one for the bad url + connection error

#

You should think smaller when making tests

#

They're unit tests after all

obsidian mortar
#

@kind meadow these are some of the first tests I've ever written so wasn't sure if all cases should be in the same test function but I definitely get why they'd be separate.

kind meadow
#

And something like this ```py
resp_file = os.path.join(TESTS_RESOURCES_PATH, "teams.json")
with open(resp_file, encoding="utf-8") as json_file:
json_response = json.load(json_file)

Should just be read one time rather than reading it for every test
obsidian mortar
#

Great - that really helps. But for a first shot it sounds like I'm headed in the right direction?

kind meadow
#

I haven't seen the code that you're testing, but it did look fine as far as I can tell.

#

The only problem is you need to split things up like I said

#

And use mocks, if applicable. If you're testing a function A, and that in turn calls function B, you should be mocking B because that test's focus should only be on function A.

obsidian mortar
#

Oh I'm sorry - here's the applicable code.

kind meadow
#

You've already been doing that for requests so it's a good start

obsidian mortar
#

Can you give me a bit of insight into what you mean by mocking the function. So when I call a function from within a test that's not the function I'm testing I should have static results?

kind meadow
#

Yes

#

And that's cause you should be limiting the scope of unit tests

#

So if a test fails, you know it happened cause something is directly wrong with that function

#

If functions all other functions which are part of your code, you'll have other tests anyway to cover those other functions.

#

And if they call library functions, well, you can assume that the libraries are tested by the maintainers of those libraries.

#

Granted that isn't always a safe assumption to make

obsidian mortar
#

Fair enough - I think that makes a lot of sense. So not only are my mock responses providing static data to avoid hitting APIs during unit tests they're providing me static data to test just the specific purpose of that function.

obsidian mortar
#

Thanks so much for your help @kind meadow ๐Ÿ‘Œ๐Ÿป

kind meadow
#

You're welcome

pliant rivet
#

Hi, can someone help me with the way I should structure my database tests? how should I do it? can you point me to some resources? They are taking too long should I drop the tables for each test?

kind meadow
#

For tests you can use transaction control to prevent committing changes made during tests to the db. Not sure what exactly you're doing so sorry if this isn't applicable.

pliant rivet
#

that sounds a good thing to do anyway

#

thanks

vagrant obsidian
#

Can anyone help me to test my Game?

proper wind
#

I'm trying to patch the __init__ method of a class in a file. I use @mock.patch('location_of_service_client_in_other_file.ServiceClient.__init__', mock.Mock(side_effect=mocked_init)). It does not seem to work however. An equivalent one, e.g. ServiceClient._wrapped_call does seem to work. Why is it not working for : __init__?

modest tulip
#
def getProjected():
            with aiohttp.ClientSession() as cs:
                ua = UserAgent()
                url = "https://www.rolimons.com/projecteditems"
                headers= {
                    "Sec-Fetch-Dest": "document",
                    "Upgrade-Insecure-Requests": "1",
                    "User-Agent": ua.chrome
                }
                with cs.get(url, headers=headers) as content:
                    contentt = await content.text()

                    for match in re.finditer(r'item_details\W=(.+?(?=;))', contentt, re.MULTILINE):
                        loaded = json.loads(match.group(1))
                        real = {}
                        for load in loaded:
                            data = loaded[load]
                            if data[5] == 1:
                                real.update({load: loaded[load]})
                        return real```
How can I convert this into requests instead of aiohttp?
marsh raft
#

I'd guess like this (untested): ```py
def getProjected():
ua = UserAgent()
url = "https://www.rolimons.com/projecteditems"
headers = {
"Sec-Fetch-Dest": "document",
"Upgrade-Insecure-Requests": "1",
"User-Agent": ua.chrome,
}
content = requests.get(url, headers=headers).text

for match in re.finditer(
    r"item_details\W=(.+?(?=;))", contentt, re.MULTILINE
):
    loaded = json.loads(match.group(1))
    real = {}
    for load in loaded:
        data = loaded[load]
        if data[5] == 1:
            real.update({load: loaded[load]})
    return real
modest tulip
#

thanks!

cursive steeple
#

Do you guys think it is safe to rely on Python's smtplib to consistently send a user's order information to them? I'm logging errors but I have this feeling that I shouldn't rely on it
I'm just using a gsuite gmail account with it

tranquil lynx
#

Hi! Does anybody use a bdd test framework in python like rspec in ruby? I use both languages and being able to describe tests in the rspec style is what I miss the most when using python. I used mamba + expects in the past but they are not actively maintained

kind meadow
tranquil lynx
#

Actually, behave is too much, like cucumber for ruby. I used cucumber extensively some years ago,but having to write and maintain features is cumbersome. Rspec (and mamba for python) really shines to me because of how easy it makes to write the tests that I want

tranquil lynx
#

Do you guys think it is safe to rely on Python's smtplib to consistently send a user's order information to them? I'm logging errors but I have this feeling that I shouldn't rely on it
I'm just using a gsuite gmail account with it
@cursive steeple yes. You just need to handle erros/exceptions to retry if they happen

marsh raft
#

so, cucumber is cucumbersome? Noted

smoky crest
#

I am writing a python package that creates stats based on photo metadata. As part of my pytest suite, I have a folder of test images. When I run it as a package or in Github CI, it can't find the folder. What's the right way to reference that in my pytest?

kind meadow
#

You're most likely using relative paths

#

Keep in mind the paths are relative to the current working directory, such is not necessarily the same directory as the python files

smoky crest
#

Sure. But how do I use absolute paths in a way that will work no matter what system is running the tests?

kind meadow
#

You can't use absolute paths unless you plan to dynamically create them

#

Which I don't recommend

#

Relative paths should be adequate

#

It just depends on the cwd when you run pytest

#

I don't suggest you make it your goal to make them work from any cwd

#

If you really want absolute path you can use __file__ to get the current modules absolute path

#

And manipulate that

smoky crest
#

Ah, ok

#

So in that case how do I use relative paths

#

do I have use OS.something to get the path at runtime?

kind meadow
#

Can you show your directory structure for the project?

smoky crest
#

sure

#

with teh images in a folder next to them there

kind meadow
#

photostats/tests/test_images should be the relative path. With that, invoking pytest from the root of the repository should work.

smoky crest
#

OK, just pushed that

#

oh, I need to change the test comparisons now

#

that worked! Thanks. (Had to also use a sort on my asserts because GH CI's Ubuntu grabs the files in a different order than my Fedora)

kind meadow
#

You're welcome

modest tulip
#

snip

kind meadow
harsh gyro
#

I have a function, stoopid, which takes input and returns InPuT. I am writing some tests for this function, and I am working to fix the failing test_stoopid_bad_input test. Currently, the test fails because stoopid does not throw the exception when receiving lists, dictionaries, or tuples because they are iterable.

To fix this, I need to update stoopid to properly reject bad input. The root of the question is, which is more proper -- to use a regexp and match alphanumeric/digits/punctuation, or to check with something is isinstance(input, str)?

kind meadow
#

It seems unpythonic to check for types

#

If other types happen to work with the function, then let them work ๐Ÿคทโ€โ™‚๏ธ

#

And if some don't work, then catch the exceptions or just let them be raised

#

You should just at the least document what kind of interface the function expects for the input type

harsh gyro
#

It does seem unpythonic, that's why I was shying away from it. For now, I did use an isinstance check but would not mind improving it. It does work with other data types, but produces the various forms of undefined behavior

#

Though one could argue that is a design flaw in the application logic itself.

night wolf
#

i got a question regarding CI platforms

#

since github published gh actions and they have a lot of cool presets, are circle ci, travis ci and such rendundant?

#

you can see actions right there in your repo opposed to external ci platforms

#

i am a bit lost

smoky crest
#

I think it's probably up to you and what you want to do

#

I use GH CI for all my GH projects

#

but I have some gitea projects and I use Drone CI on those

night wolf
#

Are there any pros that made you transfer to gh actions other than convenience

kind meadow
#

They're not mutually exclusive. You could run GH actions along with travis or whatever.

#

Maybe GH has a certain action that's more convenient to use or just doesn't exist on travis

#

Though this only applies to things that are not part of the same sequence of steps (like, you probably couldn't build on one and then test on the other without having to rebuild)

#

One pro of GH actions is that it has better integration into GH I believe. The output is visible right in the tasks page IIRC, rather than having to visit an external website.

night wolf
#

One pro of GH actions is that it has better integration into GH I believe. The output is visible right in the tasks page IIRC, rather than having to visit an external website.
yes, convenience is major point of github actions

#

but is it enough to go with gh actions rather than let's say travis?

kind meadow
#

I don't know, I don't have experience with a large number of CI services

#

From what I could tell, GH seems simplified

#

So if you work in smaller teams and don't need enterprise level features it may be better suited for you

halcyon zodiac
#

I don't know if there's a hugely compelling case to migrate existing non-trivial CI suites if they're already working without a more significant motivator, but for new CI development it's an attractive option if GH Actions provide all of the functionality that you need

night wolf
#

yes, they provide everything i need

#

but i am more familiar with travis

kind meadow
#

I had an opportunity to choose GH actions recently but decided to stick to what I'm familiar with so I can leverage my experience to get it up and running quicker.

fiery arrow
#

Hi everyone. I'm learning to unit test my stuff, so I wrote a small framework that allows me to test my functions.
How can the test names and test structure be improved here?

#

Basically, I have different objects that can be viewed and modified by users.

#

An object might not have any permission specification -- in that case, only admins can manipulate them. However, anyone can view them.

#

A permission specification consists of 3 fields:

  1. owner --- ID of the user who can reassign permissions and delete the object
  2. edit --- list of user IDs who are allowed to make any other changes to the object
  3. view --- either "anyone" or a list of IDs of those who can view the object
fiery arrow
#

But at least it passes

cobalt ore
#

@broken fern ๐Ÿ‘‹

broken fern
#

hey

#

so can you show me function1 and 2?

cobalt ore
#

i can give you the names of the functions i think, they're fairly descriptive - is that alright?

broken fern
#

that's fine, but i am trying to understand why one needs the other for testing

#

do they share data?

cobalt ore
#

Right - the reason for that is that i was wondering how to setup the test env when I have written functions for the things that would be needed

#

eg - i need data on storage - i have written a function for this, but to set up the test env i would have to create sample data and upload, using the function that i've written

broken fern
#

Well if you write your tests first, then your functions are easier to test

cobalt ore
#

so, i'm using the function to setup the env to test the function

#

i have not written tests first

broken fern
#

So let's say we have a function that sets a global variable A to some value

cobalt ore
#

is what i've said clear

#

that i have a function, that uploads to DB

#

if i want to create mock data, i need this function to upload

broken fern
#

and an other function that only does something if that is set to A otherwise it will show that A is not set

cobalt ore
#

but ofc it is daft to use the function to setup the env to test the function

broken fern
#

is it something like that?

cobalt ore
#

i think if we stick to my specific example before abstracting it will be easier for me

broken fern
#

so you are manipulating a database in the process?

#

Okay, that's what you get when you ask me to guess things ๐Ÿ™‚

cobalt ore
#

i am - so there are to be files on the data storage (not a data table)

#

just a storage bucket for files

#

i have written a function to upload to the storage, but i want to test it

broken fern
#

okay, like a directory or a remote site?

cobalt ore
#

a storage bucket on GCP, so just a directory makes sense yeah

broken fern
#

okay, so you have ftp'd or copied your files there and you want to make sure they made it

#

yes?

cobalt ore
#

I have written functions that will upload files there

#

just python

broken fern
#

okay, so that test requires that you are somehow able to tell if they files made it there, Are there queries available that will let you know they made it? ls or dir or something like that?

cobalt ore
#

sure - but i want to test the upload function as well

#

which is what i'm saying - i can't test that in the same file

#

so that i would have

test for the upload fn
tests that depend on the upload fn
broken fern
#

again, your function is successful if <fill in the blank>

#

something like files are there and they are the right size

cobalt ore
#

and as long as they're in the right order it's ok ๐Ÿค”

broken fern
#

something like that

#

okay so you can test that function.

cobalt ore
#

Right - and i would lay it out as I have described there?

#

the circular reasoning was confusing me - as i wasn't sure what was usually done here

broken fern
#

are you using any of the unit test frameworks? Pytest or unittest?

cobalt ore
#

pytest

broken fern
#

okay, so you test is a simple assert of something

cobalt ore
#

yes that's fine, what i was confused about was how to order things

#

so that I wasn't using an untested function in order to create the sample data to test with

broken fern
#
def test_upload():
  perform_upload()
  assert remote_filecount() == expected_filecount
  assert remote_filelist() == expected_filelist
#

something like that

cobalt ore
#

sure, this is not the issue though

#

the issue is using an untested function in order to create the environment to use for testing

broken fern
#

can't you create a specific environment without using your function?

#

system call or some set of data uploads?>

cobalt ore
#

๐Ÿค” maybe if i use subprocess and shell commands

broken fern
#

okay, well here's the deal, you are either doing a unit test, or an integration test or an end-to-end test

cobalt ore
#

not sure what the difference is tbh - i just have a set of functions that i wanted to test

broken fern
#

So if you can't set up the environment to a specific known state, then you have to use your untested functions to setup each the next thing. that is integration or end-to-end

cobalt ore
#

an integration test is when untested functions are used to setup the test environment?

broken fern
#

For example we had something that gets environment variables from the system and if they are not set it returns a paticular default value. ,

#

and we have another function that can set environment variables

cobalt ore
#

maybe i will just write a shell script, seems easier

broken fern
#

The system can set the environment variables for me, so in my setup I used the system calls to set specific environment variables or even unset them so that I had a known values

#

you can call the shell script

cobalt ore
#

yeah setup_test_env.sh or whatever, and just call that at the start of test_functions.py

#

although i won't test that shell script then ๐Ÿ™ƒ

broken fern
#

right, and if you do setup and teardown, you can set states either before/after all the tests in the module, or before/after each test and so forth

cobalt ore
#

yeah, I'll just pretend the shell is all perfect for now ๐Ÿ˜„ and do it like that , setup.sh, tear_down.sh

broken fern
#

Point is, that if your fixture fails that is not a test failure it is just an error

#

well think about it like this, you are not interested in testing your ability to write a shell script? you are testing your code's ability to perform a specific task

cobalt ore
#

right, for the tests the fixture (in my case this shell script) is just considered a ground truth

#

or an assumption

#

that's fine

broken fern
#

so as long as you are a bad scripter you will get errors in the FIXTURE then when that doesn't happen, you will get pass or fail from your tests

cobalt ore
#

so as long as you are a bad scripter
๐Ÿ˜„ i am indeed lol

#

it will only be a simple script tho

broken fern
#

theoretically system utilities and calls have known failure points. You can't write a file if the disk is full. You can't create a file with the same name. And so on. That you can write a proper shell script to handle.

cobalt ore
#
-> % tree tests
tests
โ”œโ”€โ”€ setup.sh
โ”œโ”€โ”€ tear_down.sh
โ””โ”€โ”€ test_functions.py

so I'll just have this

#

theoretically system utilities and calls have known failure points
yeah - i think these assumptions aren't unreasonable

broken fern
#

okay,

#

so look at the link to the pytest fixtures. It will show you how to call and recall these cleanly

#

but yes. You want absolutely trusted state for a test. Because it sucks to test something for hours only to find out it worked just fine, but what you thought it was getting for input or state was not correct.

cobalt ore
#

that link - is an alternative to using shell scripts?

broken fern
#

that is how to use pytest with "Fixtures"

#

Fixtures are very useful in tests because you can use them to setup and resetup your clean environment before each and every test or whatever you need

cobalt ore
#

i don't get why they've done assert input_value % 3 == 0 instead of assert input_value() % 3 == 0

#

presumably that's a typo?

#

or is the fixture handling that

broken fern
cobalt ore
#

yeah, they could have done that assert without a fixture surely

broken fern
#

yes but it more than anything else shows you the syntax.

#

they have a scope, and it can be down to the individual unit test or as high as the session of module

cobalt ore
#

ok fair - so if i have

@pytset.fixture
def foo():
  os.system('setup.sh')

@pytest.fixture
def bar():
  os.system('tear_down.sh')

def test_something(foo, bar):
  pass
#

it's not clear how i would do that, how it would work

broken fern
#

yes, close

cobalt ore
#

instead of

def test_something():
  os.system('setup.sh')
  <do stuff>
  os.system('tear_down.sh')
broken fern
#

probably at what your are doing that is probably sufficient.

#

I am looking for an exmaple in my stuff here, and I just don't use them that often

#

at least not in python

#

๐Ÿ™‚

cobalt ore
#

fair, would you ever use a decorator here?

#

given we basically want setup / tear_down at the start / end of each function

#

but eh, i feel that i'm being a bit hacky

#

maybe better to do something repetitive and clear

broken fern
#

That is probably closest to how yours will be

cobalt ore
#

Setting up test cases for code that manage data can be challenging
๐Ÿ˜… i feel validated lol

broken fern
#

yes

#

but once you have done it, you will find it easy the next time, it is a matter of getting your head wrapped around the concept of Fixtures to start with

cobalt ore
#

from this - the ordering is handled by the request.addfinalizer( ... ) ? in that - this will ensure that is the last thing run for a test

#

if one was to instead do request.addfinalizer(os.makedirs('a/b/c')) then the test would, at the end of the test code, create those directories

#

is my understanding

broken fern
#

right

cobalt ore
#
@pytest.fixture()
def db_setup(request):
    def fin():
        os.makedirs('a/b/c')
    request.addfinalizer(fin)

like this

#

hrmmm ok ๐Ÿค”

broken fern
#

that is the teardown part in the add finalizer

cobalt ore
#

that is quite cool

broken fern
#

right and once setup it is the argument to your test

#

before the "def fin " line is where you do your setup

cobalt ore
#
@pytest.fixture()
def env_setup():
    os.system('setup.sh')
    def fin():
        os.system('tear_down.sh')
    request.addfinalizer(fin)
broken fern
#

right then you pass env_setup to your test_xxxx(env_setup) functions

#

try one with print statements

cobalt ore
#

i need request?

#

i'm not sure what that is in their example now ๐Ÿค”

broken fern
#
@pytest.fixture()
def fixture(request):
    print('setup the fixture')
    def fin():
        os.system('tear down the fixture')
    request.addfinalizer(fin)
๏ฟผ
def test_test(fixture):
  assert 1==1
#

I didn't run that but it's what I am talking about

cobalt ore
#

yeah - request here, this is part of pytest?

broken fern
#

I think it gets the base environment of the call. you can reference it to get the arguments I think, never actually used it just ignored it ๐Ÿ™‚

#

hell, it might actually be your test_function reference ๐Ÿ™‚

#

grrr

#

I can try doign a print on it, and see what it is

cobalt ore
#

hrm, i just ran it and didn't get anything

#

let me double check

broken fern
#

well now I have to set up a folder and do some typing ๐Ÿ™‚

cobalt ore
#
-> % cat test_functions.py
import os

import pytest


@pytest.fixture()
def fixture(request):
    print("setup the fixture" * 5)

    def fin():
        print("tear down the fixture" * 5)

    request.addfinalizer(fin)


def test_test(fixture):
    assert 1 == 1
#
-> % pytest test_functions.py
====================================================== test session starts =======================================================
platform darwin -- Python 3.7.6, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: 
plugins: pylint-0.15.0
collected 1 item

test_functions.py .                                                                                                        [100%]
#

i was expecting output, perhaps incorrectly

broken fern
#

I see the output when the assert fails, just not when it doesn't

cobalt ore
#

ok, this works:

@pytest.fixture()
def fixture(request):
    print("setup the fixture" * 5)
    os.makedirs("before/yea")

    def fin():
        os.makedirs("after/yea")

    request.addfinalizer(fin)


def test_test(fixture):
    assert 1 == 1
#

well, i'm not sure how to check that it's in the right order, i need to sleep and check mtimes i guess

broken fern
#

hold on, I think it might be sent to stderr

#

pytest -s will not capture the input output so you will be able tosee it

#
=================================================== test session starts ===================================================
platform linux -- Python 3.7.3, pytest-5.4.1, py-1.8.1, pluggy-0.13.0
rootdir: /home/bms
collected 1 item                                                                                                          

test_junk.py setup the fixture
.tear down the fixture
#
test_junk.py setup the fixture
Ftear down the fixture


======================================================== FAILURES =========================================================
________________________________________________________ test_test ________________________________________________________

fixture = None

    def test_test(fixture):
>       assert 1==0
E       assert 1 == 0

test_junk.py:12: AssertionError
#

top one is success bottom one is failure

#

Pytest shows . (period) for success and F (capital F) for failure. See then right before the words "tear down the fixture"

cobalt ore
#

ah ok yes, ace... the tests have been tested ๐Ÿ˜„

broken fern
#

woohoo

#
this specifically
pytest -s                  # disable all capturing
pytest --capture=sys       # replace sys.stdout/stderr with in-mem files
pytest --capture=fd        # also point filedescriptors 1 and 2 to temp file
pytest --capture=tee-sys   # combines 'sys' and '-s', capturing sys.stdout/stderr
                           # and passing it along to the actual sys.stdout/stderr
cobalt ore
#

hrm ok, cool, good to know

broken fern
#

it is an amazingly powerful tool

cobalt ore
#

ive just accepted request is some inbuilt magic

broken fern
#

oh?

cobalt ore
#

i mean - we used it in teh fixture ?

#

it's passed in, but where from i don't know

broken fern
#

It is

 Request =  <SubRequest 'fixture' for <Function test_test>>
#

it is where the addfinalizer lives

cobalt ore
#

cool - so the fixture will be quite a bit function i guess for all the setup and tear down

#

which is fine

broken fern
#

it can be as big or as small as you need, but to be useful it needs some data and state info

#

okay @cobalt ore, we good?

cobalt ore
#

@broken fern hopefully ๐Ÿ˜… I'm just grinding through now, i think that it might work tho, thank you ๐Ÿ™
only skimmed a tiny bit of pytest before, it seems nice tho

broken fern
#

it is nice that you don't have to setup class structure to use it like unittest but it is still at least as powerful.

cobalt ore
#

i never actually used unittest, i heard it's a bit java-y tho

#

which isn't a great sign for me

broken fern
#

well it is probably based on jUnit because that was the king of unit test frameworks and so many of the other ones are based on it.

#

where it shines is with databases where you can have it create a transaction when you start and roll it back when you are done.

cobalt ore
#

where it shines
pytest? or unittest

broken fern
#

both

#

you can do fixtures in unittest too, just a little different syntax.

#

If you poke around his site, he has direct comparisons between Pytest, unittest, and I think nose

cobalt ore
#

oh right... i have never seen nose, but have heard of it

broken fern
#

shoot, his examples are so much nicer ๐Ÿ™‚ Guess that is why he wrote "The" book on python testing

cobalt ore
#

2014 tho

broken fern
#

hasn't changed much since then.

#

His podcast is pretty good too, and he is part of the other podcast Python Bytes I think

cobalt ore
#

Is there anything to be aware of when using PyTest and importing modules? It seems that I can import a module in the terminal, but when I try from a pytest file i'm getting ModuleNotFoundError, which I dont' understand as it's running in the same env

#

using pytest -m <test_script>.py changes the errors to a stream of internalerrors

thick sinew
#

!e ```py
class AmericanDate:
def init(self, year, month, day):
self.year = year
self.month = month
self.day = day

def set_year(self, current_year):
    self.year = current_year

def set_month(self, current_month):
    self.month = current_month

def set_day(self, current_day):
    self.day = current_day

def get_year(self):
    return self.year

def get_month(self):
    return self.month

def get_day(self):
    return self.day

def format(self):
    day = str(self.day).rjust(2, '0')
    month = str(self.month).rjust(2, '0')
    return f'{month}.{day}.{self.year}'

class EuropeanDate:
def init(self, year, month, day):
self.year = year
self.month = month
self.day = day

def set_year(self, current_year):
    self.year = current_year

def set_month(self, current_month):
    self.month = current_month

def set_day(self, current_day):
    self.day = current_day

def get_year(self):
    return self.year

def get_month(self):
    return self.month

def get_day(self):
    return self.day

def format(self):
    day = str(self.day).rjust(2, '0')
    month = str(self.month).rjust(2, '0')
    return f'{day}.{month}.{self.year}'

american = AmericanDate(2000, 9, 3)
european = EuropeanDate(2000, 9, 3)
print(american.format())
print(european.format())
american.set_year(2012)
print(american.get_month())
print(american.format())
print(european.format())

bitter wadiBOT
#

Sorry, but you may only use this command within #bot-commands.

fiery arrow
#

@thick sinew Why would you want these getters and setters?

#

First of all, why not use @property?

#

Secondly, why mutate a date instead of creating a new one?

thick sinew
#

I just recently started doing classes man

#

and this is my task

#

i need create all these methods

fiery arrow
#

Oh, sorry then

thick sinew
#

never mind

fiery arrow
#

Outside of that task, I would suggest doing this instead:

class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

class DateView:
    def self(date):
        self.date = date
    
    def format(self):
        raise NotImplementedError

class AmericanDate(DateView):
    def format(self):
        day = str(self.date.day)
        month = str(self.date.month).rjust(2, '0')
        year = self.date.year
        return f'{month}.{day}.{year}'

class EuropeanDate(DateView):
    def format(self):
        day = str(self.date.day)
        month = str(self.date.month).rjust(2, '0')
        year = self.date.year
        return f'{day}.{month}.{year}'
#

Because a date is a position in time, while 'american' or 'european' is a means of displaying that data.

thick sinew
#

Big thanks man!

fiery arrow
#

In python, getters and setters are usually considered bad practice. You can read about @property if you want to control setting and getting the attributes.

#

But in most cases, just expose all the attributes. You can mark some of them with _ in the beginning to indicate that they aren't supposed to be used by others.

#

And immutable classes are usually easier to work with.
So you could do this:

from collections import namedtuple
Date = namedtuple("Date", ["year", "month", "day"])
#

However, you might want to check that the date being created is correct.

thick sinew
#

Thank you

#

@fiery arrow hey

#
class MinStat:
    def __init__(self):
        self.nums = []

    def add_number(self, num):
        self.nums += [num]

    def result(self):
        if self.nums:
            return min(self.nums)
        return None


class MaxStat:
    def __init__(self):
        self.nums = []

    def add_number(self, num):
        self.nums += [num]

    def result(self):
        if self.nums:
            return max(self.nums)
        return None


class AverageStat:
    def __init__(self):
        self.nums = []

    def add_number(self, num):
        self.nums += [num]

    def result(self):
        if self.nums:
            return sum(self.nums) / len(self.nums)
        return None
#

this is another one

#

and

#

thats what i need

#

but I'll do it how you told me

#

wait a minute

fiery arrow
#

What's the task?

thick sinew
#

Implement the MinStat, MaxStat, and AverageStat classes, which will find the minimum, maximum, and arithmetic mean of a sequence of integers.

Instances of classes are initialized without arguments. The add_number method must add a number to the statistics that will be taken into account when calculating the final result using the result method. For MinStat and MaxStat instances, the result must return an integer, and for AverageStat, it must return a float number (this number will be compared with the correct answer up to the seventh significant digit).

If there are no numbers in the sequence and statistical values cannot be calculated, the result method must return None.

fiery arrow
#

Well, you can't change the requirements of a task...

thick sinew
#

Ye, I've already done it

#

but i want to do it how you told me

fiery arrow
#

Well

class Dataset:
    def __init__(self):
        self.numbers = []

    def add_number(self, number):
        self.numbers.append(number)

    def maximum(self):
        return max(self.numbers)

    def minimum(self):
        return min(self.numbers)

    def average(self):
        if self.nums == []:
            return None
        else:
            return sum(self.numbers) / len(self.numbers)
thick sinew
#

I think I'm complicating things

fiery arrow
#

I don't see the need to create a class. max and min already exist. You just have to do:

def average(iterable, default=0):
    total = default
    count = 0
    for i in iterable:
        total += i
        count += 1
    if count == 0:
        return None
    else:
        return total / count
thick sinew
#

Well

#

Thanks for mini lesson

formal portal
#

A project I contribute to is adopting pytest and I'm going through some teething issues with it. The person pushing the adoption of pytest just made a merge request that includes the following fixture in a test file:

#
@pytest.fixture
def natoms():
    return 7
#

Is this... kosher? why not just define natoms = 7 and be done with it? I don't understand the point of using a fixture for this

#

I think I just don't "get" pytest

#

it almost feels like pytest scripts aren't even really python

kind meadow
#

I don't use pytest much but I agree with you that using a fixture doesn't make much sense here

#

I suggest you ask the person responsible for that code directly what their justification for it is

formal portal
#

yeah I reviewed their MR and questioned the use of a fixture there

#

but I just feel incompetent when it comes to reviewing pytest code

kind meadow
#

I think fixtures are the main thing to understand about pytest

#

Maybe along with parameterisation

halcyon zodiac
#

Just because it offers fixtures doesn't mean you have to use them for everything

tight geyser
#

fixtures are neat and I'd like to use them more but with the way I prefer to write code, I end up not using them at all
for example my classes are simple to set up so there's no need for fixtures
I think they can hide some smelly code

halcyon zodiac
#

I don't see how they're at all related

tight geyser
#

well for example if you want to test a class you might need to instantiate it then mock out its dependencies, and repeat that same process across a number of test cases
to simplify that you could put that all in a fixture
but if your classes are easy to set up and mock, you could do it in your test case explicitly

proper wind
#

Iโ€™m working on a project that exists in a repository thatโ€™s already being tested by unittest, is it possible to just start adding in pytest tests and itโ€™ll still work? I read that pytest automatically collects unittest so im@not sure if that means the two can exist in the same space? Or should I make a new folder for pytest tests and keep them separate?

#

The code im adding doesnโ€™t impact the code thatโ€™s already being tested and vice versa, itโ€™s in the same repo for other reasons

proper wind
#

Nvm I tried it

bitter wadiBOT
#

Hey @quaint anvil!

It looks like you tried to attach file type(s) that we do not allow (.zip). We currently allow the following file types: .3gp, .3g2, .avi, .bmp, .gif, .h264, .jpg, .jpeg, .m4v, .mkv, .mov, .mp4, .mpeg, .mpg, .png, .tiff, .wmv, .svg, .psd, .ai, .aep, .xcf, .mp3, .wav, .ogg, .md.

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

quaint anvil
#

ok...

#

there are 2 lib files

#

1

#

sorry about long message

#

but it seems like it does not let me upload zip files

broken fern
#

@quaint anvil the way to handle large posting of code is to use pastebin/hastbin

quaint anvil
#

ok...

broken fern
#

!paste

bitter wadiBOT
#

Pasting large amounts of code

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

After pasting your code, save it by clicking the floppy disk icon in the top right, or by typing ctrl + S. After doing that, the URL should change. Copy the URL and post it here so others can see it.

broken fern
#

I hope that helps.

quaint anvil
#

yea thnks

molten swallow
#

@quaint anvil Sorry, but specifically testing and posting of code in another languages is not something we can help with here, that's off topic for this channel. I'm going to delete the above messages with the large blocks of lua code. In the future, if you need to post code (it should be Python code, if any), please use a pastebin service, such as the above link or a Gist.

broken fern
#

I guess I could have mentioned that. When I saw the size of it I pointed him towards the pastbin stuff, but I hadn't even noticed that it was all in lua. But then he never came back with anything,

quaint anvil
#

Ok np

proper wind
#

I have the code I'm trying to test in /bin/myfile.py and then I have my tests in /tests/subdir/test_myfile.py but in the test file I try to import myfile and I keep getting module not found. How do I set it so that I can find that module from my tests directory?

#

using pytest if it matters

knotty tusk
#

@proper wind Do you have the __init__.py file?

#

@proper wind The bin directory needs to be a package containing the myfile module.

proper wind
#

@knotty tusk I have an init file in /bin/__init__.py

#

My script does change the project root though. Maybe that's why

steady sage
#

!or-gotcha

bitter wadiBOT
#

When checking if something is equal to one thing or another, you might think that this is possible:

if favorite_fruit == 'grapefruit' or 'lemon':
    print("That's a weird favorite fruit to have.")

After all, that's how you would normally phrase it in plain English. In Python, however, you have to have complete instructions on both sides of the logical operator.

So, if you want to check if something is equal to one thing or another, there are two common ways:

# Like this...
if favorite_fruit == 'grapefruit' or favorite_fruit == 'lemon':
    print("That's a weird favorite fruit to have.")

# ...or like this.
if favorite_fruit in ('grapefruit', 'lemon'):
    print("That's a weird favorite fruit to have.")
proper wind
#

@steady sage hi! This channel is not for testing bot commands

#

that would be #bot-commands

proper wind
#

I've never written tests really for a new project til right now. I feel like it's makingme change how the code is written to be able to pass variables/capture returns better. is that common?

proper wind
#

you shouldn't really write code to "bypass" tests so to speak

#

but i do find that test help me have a clear direction on what my code/functions should be doing

#

to the point where i tend to write tests first and the actual functions later

halcyon zodiac
marsh raft
#

in theory, writing the tests first leads you to design your code better.

#

or that's what the TDD zealots say ๐Ÿ™‚ I very rarely get a chance to do it.

kind iron
#

Is virtaulenv or Anaconda better

marsh raft
#

very very different

#

virtualenv is doable with any version of python

#

anaconda is this giant thing you need to download and install.

#

anaconda comes with lots of pre-installed stuff too -- numpy, I think, and stuff like that

#

virtualenv comes with nothing (which is sort of the point)

soft mango
#

Perhaps the question was about virtualenv vs conda, which is a legit comparison question, though not relevant for this channel

tough pewter
#

any one familiar with tensorflow?

proper wind
#

hello i was wondering why my code isn't working is there anyway to send it through the chat without it being a giant mess

kind meadow
#

Is it related to software testing? If not, you'll want to claim a help channel at the top of the server in the "available" category

proper wind
#

How does the script automatically delete the line of code?

I want the script to automatically edit (even when in exe) and delete a few lines of its code```
elder sun
#

You would have to create a python script. I recommend using os.path, os.remove and the open() feature in python. From there you would just have to overwrite the script. However you would have to have sudo because it would probably be an open file if you're running the script you're trying to change @proper wind

verbal timber
#

Hey anyone used selenium here

sour vector
#

Yeah.. @verbal timber

verbal timber
#

hey i am not able to install tkinter

#

it saying not able to find the file may i know the error

visual sentinel
#

I'm trying to learn unittest.mock.mock_open https://docs.python.org/3/library/unittest.mock.html#unittest.mock.mock_open
But I'm a slow learner. Can someone tell me why their example, reproduced below, produces fileNotFoundError?

from unittest.mock import patch, mock_open

class TestMy_Module(unittest.TestCase):
    
    def test_opener(self):
        with patch("__main__.open", mock_open(read_data='bibble')) as m:
            with open("foo") as h:
                result = h.read()

        m.assert_called_once_with("foo")
        assert result == 'bibble'```
I had thought that it would pretend to open a file named foo, rather than try to find one.
soft mango
#

Looks like you haven't followed the example completely

#

You need to assign the mock_open to m, rather than use it directly in the context manager

#
m = mock_open(read_data='foo')
with patch('__main__.open', m):
   ...
visual sentinel
#

Thanks Fiddle. Well I just copy, pasted it.

soft mango
#

Ah, my bad, I read the wrong example

visual sentinel
#

No problem. Just found 3-4 threads saying they had to use "builtins.open" instead of "__main__.open". Example works now.

vale tulip
#

I am using the scrapy webscraper and I have a few questions would this be the right channel?

kind meadow
#

No, web scraping is not software testing.

#

A normal help channel would be better

marble hatch
#

Is there something roughly like selenium but for sending input to virtualbox machines, or even specific windows/programs on them?

kind meadow
#

This is not the appropriate channel to ask

#

I wonder where people are getting the idea that software testing = web scraping because I am seeing quite a few questions incorrectly come in this channel for that topic.

#

Not just today.

marble hatch
#

@kind meadow i'm not asking for help scraping, I'm trying to understand what tools are available to help write integration tests for a game server implementation. The game only has win32 and linux desktop builds, so controlling client instances seems to be a necessary part of testing the server.

#

Everything related to testing your Python applications and libraries, and discussion of testing as a whole.
my understanding is that asking about automating the client side actions for integration tests falls within the channel topic

marble hatch
#

The reason i mentioned selenium is that i'm looking for libraries like it in that they control input events and maybe even navigating ui, but for the desktop

trim meadow
#

mabye pynput?

wicked radish
#

What is this channel for, exactly? Do people here test other people's software? Or is it more for asking questions about testing software?

marsh raft
#

I'd guess the latter

#

not sure though

worthy trail
#

I'm writing an API in flask on a remote workspace on vscode, one of the endpoints is particularly slow and I'm trying to figure out why. I hear profilers are meant for this kind of thing, but i've never used a profiler. What's a good profiler to use on a remote workspace

marble hatch
#

@trim meadow pynput is a step towards what i need,ty!

marble hatch
left steeple
#

I need help it says i need an if statement but i have one

marble hatch
#

@left steeple try the help channels

empty pasture
#

Hey everyone, new to the discord but im searching for a guide on python testing. Something that covers mocking and fixtures. I cant seem to find a good guide for beginners. Tia

radiant pollen
#

has mocking, but I can't recall if fixtures are covered

empty pasture
#

@radiant pollen thanks taking a look

radiant pollen
#

I just watched it ๐Ÿ˜„

swift pollen
#

note that this more about TDD as a philosophy, and works through django first, but it's a good starting place

proper wind
#

Hi guys

#

I am new here

jaunty helm
#

anybody have a utility they like for functional testing of a cli?

cobalt ore
#

How does one typically test something which writes a file as output?

For example, if i have some code that creates an xlsx file, how would you go about testing that?

All i can really think of at the moment is writing the file, opening it up again and checking that it has the correct content... is that about it?

kind meadow
#

Patch the open() function to mock it

#

And make assertions on the arguments passed when write() is called

cobalt ore
#

@kind meadow not too sure i follow, is this a common pattern that i could search for?

#

Patch the open() function to mock it
here you're saying use the open( ) function to create mock data?

kind meadow
#

Yeah, is called patching and mocking

#

If you look at the unittest.mock documentation you should get a better idea of it

#

I'm saying to patch open() so that it's a mock, and thus also returns a mock

#

And the mock it returns will be a mock for the file object.

#

So instead of actually opening and writing to a file, you're just using these dummy objects which outwardly pretend like they're doing all that

#

But they actually keep track of calls made, arguments passed, etc

#

Which allows you to make assertions for testing

cobalt ore
#

@kind meadow ok thanks, i'll be using pytest, hopefully there's a similar thing. I think there was something that someone showed me before in this channel of a similar nature.

marsh raft
#

How does one typically test something which writes a file as output?
@cobalt ore rewrite it so that it doesn't ๐Ÿ™‚ I'm 80% serious. I try to separate "i/o" (reading or writing files, talking over the network, etc) from "logic" as much as possible; I make the i/o code as simple as possible -- few if any "if" statements, e.g. That way I only need to test the i/o stuff superficially -- like, if I've seen it work once, that's plenty. Whereas the logic, which can be nasty, and thus needs lots of tests, I write unit tests for

cobalt ore
#

@marsh raft i kinda struggle a bit here... I have a function that will take in a file type and write out all the meta data to xlsx files, basically.
So I could split that into two functions - one which creates the metadata structures, and another that writes those to a file

#

I guess I can take the iO on faith ๐Ÿค”

marsh raft
#

yep

#

you don't have to take the IO on faith; as I said above, you should at least run the code by hand once or twice to ensure it works.

#

But if that IO code is simple enough, you don't need anything beyond that.

#

I've been programming a long time, but I only started doing this in the last few years after a very good programmer that I worked with emphasized it. It's not hard to do, and it saves a bunch of hair-pulling.

cobalt ore
#

fair, that makes sense

marsh raft
#

!paste

bitter wadiBOT
#

Pasting large amounts of code

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

After pasting your code, save it by clicking the floppy disk icon in the top right, or by typing ctrl + S. After doing that, the URL should change. Copy the URL and post it here so others can see it.

marsh raft
#

kinda dumb but hopefully it conveys the flavor

cobalt ore
#

yeah, cheers... A lot of this is ported over from notebooks which I'm usually a lot looser in as they're often not hanging around for long / a lot gets scrapped

#

i'm actually really good at writing crap code, i realise reading this ๐Ÿ˜„

hidden ibex
#

why do people test their code?

#

can't you just run it and see what happens?

halcyon zodiac
#

Thatโ€™s what testing is

#

Just...automated

hidden ibex
#

but you still need to check it either way, so why?
seems overrated

cobalt ore
#

@hidden ibex if it seems over-rated then maybe it's a sign you can look at it later

#

I have started testing more since writing things and having them change a lot, and wanting some confidence that i haven't broken something elsewhere. There are other examples/reasons i'm sure

hidden ibex
#

how do you test something?

#

is it the same as asserting?

fervent ruin
#

Hello,

#

Everyone

#

I am here for a help.

#

but getting 405 error when sending a post requests.

#

How can I login ?

balmy shell
#

check the network tab in the devtools of your browser

swift pollen
#

got a question about TDD -- I'm writing an app in django that performs lots of functions on a db -- whats the best approach to mocking a db? just creating loads of objects in the test suite? or making an actual 'fake' db for testing purposes?

marsh raft
#

best approach: don't ๐Ÿ™‚

#

write most of your code to deal with dumb python data structures -- dicts, lists, etc

#

test the bejesus out of those

#

then write super-simple functions, ideally with no "if" statements or loops or anything, that read and write those data structures to and from the db

#

testing db stuff is hard, so you want to have as little "db stuff" as possible

#

this way it suffices to just see it run successfully once or twice

#

@swift pollen โฌ†๏ธ

hidden ibex
#

does anyone know mutation testing?

kind meadow
#

@supple junco You should reset your credentials

#

Also this isn't related to software testing. Claim an available help channel instead

supple junco
#

wich one does it belong to then?

kind meadow
#

A normal help channel

#

See the category on the top

#

2 green check marks

#

But seriously, reset your password

supple junco
#

its a test account don't worry

#

it's all fake info

visual sentinel
#

When unit testing a simple function, does it matter that it relies on an import at the top of it's module, e.g. datetime, or re?

jaunty helm
#

What do you mean? Are you asking if you have to test imported code? No.

visual sentinel
#

Thanks. I just wondered if it was still a unit test, or an integration test(and should go in separate module).

jaunty helm
#

ahhh, so unit vs integration depends on how youre testing. it doesnt matter if the code your testing relies on imports or not.

Unit testing looks at testing specific functions.

#

integration and functional testing look at testing from the outside bigger picture

#

'if i call the program, do i get a final output that i expect' is functional, where as 'does my function turn_str_input_into_int_list(input: str) -> List[int] do what i expect it to

visual sentinel
#

Ok. Thanks very much Avian.

marble hatch
#

@hidden ibex imagine you're working on a big project, like a game. it'd take a long time to launch the server and the client, and you want to make some changes to a very specific part. which of the following would you rather do?

  • write code that takes a few seconds to run to make sure your crafting mechanics work, and lets you know any time you break them
  • manually launch the server and game, and do it all by hand, taking 40 minutes each time
hollow basin
#

Are code reviews a real thing in industry? In my class they sound super formal with designated roles and stuff.

#

I can't imagine why something that heavily specified would be needed.

balmy shell
#

depends on the company, but yes, they're real

soft mango
#

Yup I do code reviews at work

#

And I find a crap ton of bugs

#

So it's definitely worth it

#

Technically there's no role for code reviews, everyone is expected to do code reviews as well as dev

#

In practice only the more experienced devs and those with approval rights will do code reviews

balmy shell
#

wow "approval rights", never been at a company with that

hollow basin
#

I manage an open source project and I look at all the pull requests

#

And make sure that it would still work if I merged it

#

That's about it.

soft mango
#

I do that too, just in greater detail. I don't just make sure that nothing breaks, but also that the new feature works, and that the new feature is the correct thing to be built.

hollow basin
#

I meant to imply that I do those thing as part of "looking at it", but I guess that wasn't evident.

soft mango
#

By looking at it, do you just mean you look at the diff of the code and that's it?

hollow basin
#

I make sure that the code looks like it makes sense and that the unit tests that came with it can only pass if it does what it's supposed to. And that they pass.

#

But also that they don't cause other tests in the package to fail.

soft mango
#

Right. That's still a code review, and tbh that's the level that most of my colleagues do their code reviews as well

#

I do it differently by doing a deep dive, but I also catch a lot more errors than my peers that way

hollow basin
#

I've never gotten a PR robust enough for me to learn about that.

#

Well, there was one time I got a PR that was meant to implement something that I didn't understand how it worked at all.

#

And it didn't come with any tests. So I wrote tests to make sure that the surface level behavior was what I expected.

#

And it wasn't.

soft mango
#

Oh, if I was asked to do a code review on someone's code and they hadn't written tests for it, I would just send it straight back

hollow basin
#

I tried to send it straight back after I demonstrated that it didn't work

#

But then I was told that it was my job to figure out how it worked (which would require having taken courses that I wasn't even eligible to take yet) and that I shouldn't have even written the black box tests.

#

But now I'm just expressing how jaded I was by that occasion.

#

Rather than discussing my thoughts on code reviews.

soft mango
#

Well, it might be your job to understand how it works, but it's their job to prove that it works. And if they haven't written tests for it, they haven't done that

#

It's also their job to write code in a way that isn't brittle, and again, if they don't write tests, they haven't done that.

#

But, to the subject of code review, I feel that I have to load the person's code into my IDE to do a proper review of it

#

There are a few reasons for that

hollow basin
#

Because it does a lot of the analysis for you?

#

And you can step through it?

soft mango
#

Yup, two reasons right there

#

Also, also the files that are changed are shown in a pull request. I feel that, in order to review it effectively, I have to see how the code sits within the system

#

I can only really do that in my IDE

#

There's another reason as well, which doesn't really apply to a lot of people

#

Our code review tool has some real issues with trying to line up the diffs in the code

#

If there are big changes, the code review tool just can't deal with it correctly

#

PyCharm's diff tool is much better in that regard

hollow basin
#

Pycharm is pretty Bae.

soft mango
#

Oh absolutely

#

It took me a while to get into it, because I started out with something quite simple, so PyCharm was initially overwhelming to me

#

But once you get into it and know all its features, it's hugely useful

hollow basin
#

The first python ide I tried to use was spyder

#

And I didn't know anything about programming

#

So when I got pycharm, I went in with the expectation that I'd initially have no idea what I was looking at.

#

Though I sometimes use sublime if I don't want to wait ten minutes for pycharm to open.

soft mango
#

Ha fair enough

#

I use VS Code if I need something lighter

hollow basin
#

Nope, you need to use one of two extremes. Vim or pycharm.

soft mango
#

I want to try to learn the Vim commands someday

hollow basin
#

You can use vimtutor if you want.

soft mango
#

i tried that a number of times, but I feel that one has to use it actively when they code

#

Unfortunately I find that for me, learning it gets in the way of the coding process. I have to think not just about what I want to code but how to code it using Vim

#

If I want to learn Vim one day I'll have to get past that stage

hollow basin
#

The only time I ever use vim is if I'm on an ssh connection and I don't have pycharm open.

soft mango
#

For me I only use it when I am using Git on command line and it's the default editor

#

But even still I just stick to hjkl and basic : commands

hollow basin
#

Are you writing epistles in your commit messages?

soft mango
#

Lol XD Well, sometimes one forgets to use the -m flag

#

But yeah, it's rare that I use Vim

#

Even if I do use it, I would just use IdeaVim with PyCharm

#

PyCharm is too good to give up

deep meteor
#

pycharm is crap get vscode

soft mango
#

I use both and definitely prefer PyCharm

deep meteor
#

Pycharm is well good looking and nice for beginners but i only had issues with it and since i also do c# and sued to vscode i might just stick with it.

hollow basin
#

Pycharm isn't meant to be cross platform for python and c# out of the box, I don't think.

#

Though there might be an add on for that

soft mango
#

I think if you want cross-platform you use Intellij with the relevant extensions

#

But, saying that PyCharm is "nice for beginners" is way off the mark IMO

deep meteor
#

I have been rather stuck on what to choose if i should stick to c# and just use that or learn python and be done with it, i use XAML for gui there and in python i use tkinter but it dosnt look that great, can anyone give me some advice?

hollow basin
#

But I'm pretty sure tkinter is just bad.

soft mango
#

Yeah I've heard bad things about it

#

And that one should use qt instead, I think? I haven't done much UI stuff so idk

deep meteor
#

Yeah aware of that channel just posted wrong my bad.

#

I don't use graphical deisgners i preffer to code it.

soft mango
#

Well, tbh, we've been talking about editors in here rather than software testing so we aren't any better XD

deep meteor
#

Well testing a new guy might be "software-testing" ๐Ÿ˜„

#

GUI*

hollow basin
#

@soft mango there is one IDE that's terrible

#

And it's android studio

#

But that's because it's designed to do a terrible thing.

soft mango
#

Heh

#

You don't like Android dev?

hollow basin
#

No. By the time I open Firefox and android studio and the android emulator, my computer is basically inoperable

#

But I can't pick one to not have at any given time

soft mango
#

Ah. Well, Intellij is pretty resource heavy, and I imagine the emulator would be too

hollow basin
#

Intellij does a subset of what android studio does.

#

Android studio is larger and more sinister.

soft mango
#

Huh. Interesting. I wasn't aware lots of stuff was added onto Intellij to make Android Studio

hollow basin
#

I believe so.

#

It might not be that they added as much as I thought

#

But I couldn't find a way to get the same functionality with just intellij add ons.

soft mango
#

Right ok

#

Unfortunately it seems the only way around that is to get a new computer

#

PyCharm just wouldn't run on my old one so I upgraded

hollow basin
#

This is a gaming laptop

#

It runs games fine

#

Except for the most resource intense ones.

soft mango
#

Right. What are the specs, out of interest?

hollow basin
#

No idea.

#

It's a dell inspiron 15

#

A bit over two years old.

#

When I graduate I'll get a behemoth machine.

soft mango
#

If you go to Settings - System - About, you can look at the specs

#

I tried googling your machine but seems like there are a few with that name

hollow basin
#

I'm running a Gradle build, so I dare not interact with the machine until it's done.

soft mango
#

lol ok

#

Gradle - there's something that's black magic to me. Never understood it properly

hollow basin
#

I don't even know what it is.

#

I guess it's like a convoluted make file?

soft mango
#

Perhaps

#

I should know but don't

marsh raft
#

I have that vague sense too

#

probably "Like a Makefile, but all XML for your convenience and enjoyment"

#

because, you know, Java

lament prairie
#

Hey, guys, what's the proper way to test closures?

#

Separately test that it correctly captures the arguments and then create a function via closure and test it?

weak spoke
#

hello, I have a project here called SuperPyOS- it is an OS written in python designed to run alongside your other system

#

it only uses 3 other modules, the rest are from the PSP

proper wind
#

Hi, i have a problem with selenium in ubuntu with firefox, cannot change of tabs. I try with driver.switch_to.window(driver.window.handles[0]) and driver.navigate().back() but not found

jaunty helm
#

has anyone tested a repl? i cant find a way to do it

marsh raft
#

only repl I know of is the one built into python, and since I didn't write it, I don't feel the need to test it

long ember
#

ipython is essentially a better version of the built in repl. Its pretty nice, except it gives these weird errors randomly somtimes

#

but I guess that isn't what you're asking about given the channel

stable tinsel
#

Hi i have this

class TestVar:
    def __init__(self):
        self.test = 1

    def get_test(self):
        return self.test


if __name__ == '__main__':
    t = TestVar()
    a = t.get_test()
    a = 6
    print(a)
    print(t.get_test())

Result

6
1
8

But i want this result

6
6
8
marsh raft
#

I only see two calls to print and yet both your examples show three lines of output

#

when I run it I only get two lines

#

so you're not showing us the code that produces the output that you showed us

#

...

#

which is gonna make it awfully hard to help you

stable tinsel
#

sorry

#
    t = TestVar()
    a = t.get_test()
    a = 6
    print(a)
    print(t.get_test())

    t.test = 8
    print(t.get_test())
marsh raft
#

so let me get this straight

#

you're setting a member to some value

#

but when you print it, you want it to be some other value

#

I can't imagine why you'd want that, nor can I think of how you could make that happen

stable tinsel
#

wait

#
class TestVar:
    def __init__(self):
        self.test = 1

    def get_test(self):
        return self.test


if __name__ == '__main__':
    t = TestVar()
    a = t.get_test()
    a = 6
    print(t.get_test())
#

what is the result of the print?

#

think

spice stag
#

1

stable tinsel
#

ok, for me i want 6

#

i come from C#

marsh raft
#

I'm guessing: you're expecting that a is a sort of second name for t.test, and that by changing a, it should also change t.test

#

that's not insane, and some things in python do indeed work that way

spice stag
#

i came from python xD

marsh raft
#

but unfortunately, integers don't

stable tinsel
#

i dont know much about python so

spice stag
#

okay

stable tinsel
#

dont have way to make "protected" self.test var, make internal in TestVar

spice stag
#

want to learn python?

stable tinsel
#

and only u can get_test and modify if u want

#

and affect to the self.test

spice stag
#

but the output will be 1 on the above qus

stable tinsel
#

yeah, i try to "protect" the self.test to direct change,
Only can change the value if you call get_test() and change the value

#

and affect to the self.test

#

so in my test, for i want is self.test change to 6

spice stag
#

protected or private?

stable tinsel
#

without set with t.test = 8

#

private sorry

#

xD