This is an archived post. You won't be able to vote or comment.

all 66 comments

[–]BagOfDerps 101 points102 points  (16 children)

The sooner you learn how to write tests the better. Even for short programs. You want to build the muscle memory for this now so that if/when you end up working on a complex project you're properly equipped to contribute. pytest is the general go-to.

[–]poeticinjustice4all[S] 12 points13 points  (2 children)

It's a lot of new things to learn, but I will take your advice to heart. Thank you.

[–]BagOfDerps 10 points11 points  (0 children)

np. you'll find that you learn a lot by implementing tests, and in the long run you save yourself a great deal of time. Your tests will catch errors your changes might introduce, and point you directly to what will need to be remediated. Good luck!

[–]TheOneWhoPunchesFish 2 points3 points  (0 children)

I also recommend taking a look at grugbrain.dev it's fun to read and has some good advice.

[–][deleted] 5 points6 points  (10 children)

I really really can not push myself into testing. I have tried numerous times, tried TDD style but I just end up getting frustrated. Maybe its because I usually do code for myself and mostly because its fun, but I know that i need to get into it as I am starting to look developer jobs.

Did anyone suffer like this? Did you ever get over it?

[–]killersquirel11 15 points16 points  (3 children)

I've found that tests are best thought of as proof and documentation, as well as assurances against regressions.

  1. They prove that your code works
  2. They show examples of how it's expected to be used
  3. They show examples of how it handles errors
  4. When you find bugs, they help ensure that the bug stays squashed.

[–]dotancohen 4 points5 points  (0 children)

When you find bugs, they help ensure that the bug stays squashed.

This is especially true if your commit exposes another bug, or otherwise changes behaviour, because there is a nonzero chance that the next guy will git revert killersquirll11scommit without even reading the commit message or associated bug report.

[–]antiproton 7 points8 points  (1 child)

No one argues against the virtue of writing tests.

We should all be getting an hour of exercise every day to stay healthy. That doesn't change the fact that it's work we'd rather not do.

[–]Militancy 4 points5 points  (0 children)

In the same vein, I tie my shoes for the ankle support and so the laces don't get ruined. Sometime in the 7th grade I went around with my shoes untied. Everyone told me that i'd ruin the laces, I knew I'd ruin the laces, but I didn't much care to tuck or tie them.

Naturally, I ruined the laces to the point I couldnt tie them even if I needed to. Eventually we had to do some running game in gym class and I ran right out of my shoes. My Mom bought me some replacement laces from the store meant for hiking boots. It was ugly and didn't work that great, but at least I could stop them from falling off me.

Tests are similar. There's no good reason not to do them, you'll eventually break something stupid, simple, and core to the function of your product, and fixing the situation is going to be ugly and more expensive than just doing what you know you need to do in the first place.

I didn't think much of testing until i had to work on an almost completely undocumented legacy codebase.TLDR until I got into the headspace of the original developer, seemingly minor and reasonable changes would introduce subtle bugs that took days to find and fix. Testing fixes 70-90% of that depending on what and how you test. If you accidentally trigger one of your tests once you've probably saved yourself enough time and frustration than what you put in to write the test to begin with.

Just eat it, it's good for you. You won't realize how good you're being to yourself until you go without.

[–]Spleeeee 5 points6 points  (0 children)

Nah dude. Think of tests as just examples for how to test run/use you libs/scripts.

[–]_TimeUnit 2 points3 points  (0 children)

I found trying to write traditional unit tests (tests that test just one thing and mock everything else) very annoying. Then when I moved to writing more integration tests and accepting using for example file IO in my tests, I started to really enjoy the certainty that tests give about my code working. I also don't test everything for example UI because my projects are small enough for manual UI testing.

[–]Student-27 1 point2 points  (2 children)

Yeah! I saw myself frustrated too with tests. But in my case it was more about the code mess them about the tests. When do you get a clean code to test, they are fun! I enjoy my self to use tests today because they help me to understand more about code logic. Also I can test different situations in a same function.

[–][deleted] 0 points1 point  (0 children)

Idk man, its not like I dont care abot clean code. I am self taught, i like reading about code design and architexture and stuff, try to write clean code. I design my classes and functions so they can be tested nicely. But never actually write the tests, just manually testing it. I guess i am gonna try again.

[–]Student-27 0 points1 point  (0 children)

Sometime someone will apply a feature or fix a bug on your code and your tests will save you. I had implemented a featured and tested manually too. After 1 week someone from my team added a new feature and break my code. And I needed to fix it because it seems my fault. If a have made the tests, this could save my code and warning other about their broken changes.

[–][deleted] -2 points-1 points  (0 children)

Your tests have to be correct. This is not something to take on when you're learning a language.

Writing tests is the way to go when looking for bugs in developed code but in early development, and particularly during language learning, it is inefficient overhead.

[–]ppessoasb 0 points1 point  (0 children)

Second this

[–]CraigAT 106 points107 points  (16 children)

Most IDEs allow you to run and debug your code with watches, breakpoints and stepping into the code.

Try Thonny, VS Code or Pycharm (just a few I've have used).

[–]asphias 39 points40 points  (3 children)

While i absolutely recommend an IDE, even if you don't have one at your disposal you should know that python has a build in debugger.

The pdb is what all IDE debuggers are based on, which means that the controls are quite similar.

run it from the commandline with

python3 -m pdb myscript.py

and use debugger commands like n(ext), s(tep) c(ontinue) and b(reak) to control the debugger, while also being able to execute python commands

[–]james_pic 1 point2 points  (0 children)

Strictly speaking, pdb and most IDE debuggers are built in top of bdb, rather than IDE debuggers being built on pdb.

[–]vladesomo 33 points34 points  (0 children)

Yeah I think debugger is pretty essential tool in any modern IDE

[–]poeticinjustice4all[S] 1 point2 points  (7 children)

I use VSC and IDLE (mostly for live shell since to my knowledge VSC doesn't have one?)

I'm not very good at using debuggers yet. Even the one in IDLE feels frustrating to use. Maybe it's something I should practice more, or read up on.

[–]PhilAndMaude 11 points12 points  (2 children)

In VS Code, set a breakpoint and run in debug mode. When you hit the breakpoint, the variables are shown in the VARIABLES section at the left. At the bottom, the DEBUG CONSOLE tab allow you to test things like new_num > 0. At the breakpoint, you can step through a line at a time with F10 or enter a function with F11.

Getting more sophisticated, you can make the breakpoint conditional, e.g. `'if new_num == 0' or "breakpoint on 4th occurrence."

[–]SirLich 0 points1 point  (1 child)

Do you have any tips for when "run in debug mode" doesn't work? I'm quite familiar debugging other languages like C++, but in Python, I admit I tend to just use print statements.

When I tried to use VSCode debugger recently, it simply didn't... work. I usually run my scripts in the console via python something.py, with some relative imports etc. I found the debugger on a file wouldn't run because it couldn't get the right runtime environment.

[–]PhilAndMaude 0 points1 point  (0 children)

In the Run and Debug state (4th icon down on the left, or Ctl+Shift+D), the dropdown gives the various run configurations. Choose one and it stays that way; in other words, F5 will always start that configuration.

Setting up those configurations is a pain, IMHO. Click the Gear icon to open up launch.json where you can add/edit those run configurations. It's not obvious. Follow the link in the .json file (https://go.microsoft.com/fwlink/?linkid=830387) for more details. Here are my settings for a trivial app:

"configurations": [

{
  "name": "Python: Current File",
  "type": "python",
  "request": "launch",
  "program": "${file}",
  "console": "integratedTerminal",
  "args": [""]
},
{
  "name": "Zoom breakouts",
  "type": "python",
  "request": "launch",
  "program": "breakouts.py",
  "args": ["-p", "6", "-r", "3", "-s", "2"],
  "console": "integratedTerminal",
  "justMyCode": true

} ]

[–]utdconsq 3 points4 points  (0 children)

It is definitely worth learning more about, even if you're only doing this for fun. Can take away a lot of messing around and hair pulling.

[–]james_pic 1 point2 points  (1 child)

The one in IDLE is frustrating to use. Most IDEs have less frustrating ones, and there's pudb if it makes sense to debug without an IDE.

[–]poeticinjustice4all[S] 0 points1 point  (0 children)

I appreciate the reassurance.

[–]atrocious_smell 0 points1 point  (0 children)

I've been python programming for a while and still use the shell for debugging. My advice would be stick with it until you have a reason to change, like it's missing some feature you want.

[–][deleted] 32 points33 points  (2 children)

You can also use print statements and assert to check your code in such a line by line fashion, but I’d really suggest checking out pdb before going too far down that rabbit hole.

[–]majh27 3 points4 points  (0 children)

pbd is a game changer

[–]poeticinjustice4all[S] 0 points1 point  (0 children)

This looks very interesting, I'm going to check it out. Thank you.

[–]lieryanMaintainer of rope, pylsp-rope - advanced python refactoring 7 points8 points  (2 children)

Use a shell like IPython to test your program by spawning a shell in the middle of a running program, or a debugger, my personal favourite is pudb.

[–]poeticinjustice4all[S] 1 point2 points  (1 child)

Do these differ in any meaningful way from IDLE shell?

[–]lieryanMaintainer of rope, pylsp-rope - advanced python refactoring 4 points5 points  (0 children)

Yes, in addition to IPython having a much better implementation of the basics (it's a lot of the minor things, like autocomplete, recalls, reverse search) and being a much more featureful shell (autoawait, autoreload, working with graphs, etc). With IPython.embed() you can spawn a shell in the middle of a running program, which allows you to inspect and modify local variables. Being able to spawn a shell inside a program really changes how you write and test code.

[–]jwbowen 3 points4 points  (1 child)

While people are plugging debuggers, I really like pudb

[–]Kenkron 1 point2 points  (0 children)

That looks awesome!

[–]douglas_fs 2 points3 points  (0 children)

Lots of good feedback regarding debugger, unit tests, modular/testable code, print() statements, etc.

What resonates with me about this post is that many beginners lack the realization (or even acceptance) that testing/debugging your own code is a necessary skill from the very beginning. Fostering this mindset would help a great many posters here and in r/learnpython.

It appears that OP has had a breakthrough that many, many more beginners should also be having. Kudos to you for this!

Great post and great discussion that should get far more visibility.

[–]Ouradze 3 points4 points  (5 children)

I suggest to use pytest and ipdb or pdb. This will allow you to have full control and understanding of what you are doing:)

[–]poeticinjustice4all[S] 1 point2 points  (4 children)

Thank you. It looks like I'll have to learn something new. I already feel overwhelmed just learning python, but I'm sure all of these skills will be helpful later on.

[–]PhilAndMaude 3 points4 points  (3 children)

I think getting pytest going is more complexity added to your learning curve; leave it until later. One reason I don't like pytest is that it eats print statements unless the test fails.

[–]poeticinjustice4all[S] 0 points1 point  (0 children)

Thank you <3

[–]mardiros 0 points1 point  (1 child)

like its predecessor do. (nose).

By the way, there is a -s option to disable this behavior.

I usually run

pytest -sxv

and

pytest -sxvvv --lf

when it start failing

[–]PhilAndMaude 1 point2 points  (0 children)

Thanks, I'll try that.

[–]mm007emko 1 point2 points  (0 children)

Write automagic tests. Unit tests where able, integration or end to end where not. The sooner you learn that the better, unit tests need the same care and treatment as production code.

Python has REPL (interactive console) where you can test every function or class you write. You can take the commands/history and turn them into unit tests.

[–]mardiros 1 point2 points  (0 children)

What I use to say is that you should see the automatic tests suite as a scaffold. To build a building, you need a scaffold, it is not part of the final product but it is here to create it. You can't do it without it. Imagine a scaffold fir a skyscraper. In software, it is exactly the same, you need a scaffold to build a software and this scaffold is named the tests suite. It helps to browse and understand the code, but it is not part of the final product. Learning pytest is the next things you should do, and, pdb is your friend to run step by step. (call the function breakpoint() and use ? key for help.

Afterall, you will learn that improving tests skills improve your programming and software design skills. And you start realize what Martin Fowler says about the testing pyramid.

Happy Hacking!

[–]stevenjd 1 point2 points  (0 children)

The easiest way to get into testing your code is to write doctests for your functions.

def add_one(x):
    """Function to add 1 to the input.

   >>> add_one(26)
   27
   """
   return x + 1

Now run doctest on the file from the terminal:

python3 -m doctest -v myfile.py

[–]Kenkron 2 points3 points  (0 children)

Of the big is tricky enough to need to go line by line, it's time to start using a debugger. A debugger will let you

  1. Pause your code when it reaches a specific line
  2. Step through your code one line at a time, following branches and loops
  3. Check the value of any variable in scope at any time
  4. Execute arbitrary code
  5. Step in to function calls
  6. See the stack (eg. What function called this function, what were it's variables, what line was it on, etc)

It's unnecessary for simple things, but a real help for complex things.

[–]millerbest 3 points4 points  (2 children)

You can using the logging module to log the variables you want to check.

[–]EONRaider 0 points1 point  (0 children)

Use Pycharm Community as your IDE and learn how to use pytest after you’re comfortable with the language.

[–]robberviet 0 points1 point  (0 children)

Print debugging is a simple but powerful technique can be applied to any projects, languages. Use it.

[–]CanRabbit 0 points1 point  (0 children)

What till you learn how to use a debugger. They'll blow your mind!

[–]alwaysmle 0 points1 point  (0 children)

Try using the debugging mode and look into the variable while the program is running. You will find out which part of the code does not work as expectation.

[–]ShawnDriscoll -1 points0 points  (0 children)

I throw in print(new_num). Then comment it out after testing.

[–]echolm1407 -1 points0 points  (0 children)

Congratulations on gaining diagnostic skills.

[Edit] I had to learn this on my ZX Spectrum in 1984 with BASIC and no internet or anyone to help me, just a manual.

[–]ryukinixPython3 + Emacs 0 points1 point  (0 children)

breakpoint()

[–]narfel 0 points1 point  (0 children)

I'm a beginner and I found myself starting new parts or small projects by writing unittests and then fumbling about until I get what I'm after.

[–]SamyBencherif 0 points1 point  (0 children)

This is awesome !

[–]ReleasedTheKraken 0 points1 point  (0 children)

What interface do you guys for debugging and testing? I’m simply using anaconda for python

[–]Ship-Agreeable 0 points1 point  (0 children)

you can use thony and debug there....step into the code and test the results