Skip Navigation

Search

Why won't my Python unit tests run?

Hello! I'm attempting to follow some tutorials on unit testing with Python. One of them is a video tutorial Unit Tests in Python on the Socratica channel. Everyone in the comments seems to be making out just fine, and I’m following the instructor’s directions to the letter, yet I get a different result. It’s driving me mad lol.

In the video, the instructor creates two text files, one called circles.py in which she defines a function circle_area(r), and another called test_circles.py in which she writes some unit tests. In my attempt to follow along, I've ended up with two files structured like so:

/home/yo_scottie_oh/Projects/PythonTutorials/Socratica/Circles ├── circles.py └── test_circles.py

circles.py:

``` from math import pi

def circle_area(r): return pi*(r**2)

Test function

radii = [2, 0, -3, 2 + 5j, True, "radius"] message = "Area of circles with r = {radius} is {area}."

for r in radii: A = circle_area(r) print(message.format(radius=r,area=A)) ```

test_circles.py:

``` import unittest from circles import circle_area from math import pi

class TestCircleArea(unittest.TestCase): def test_area(self): # Test areas when radius >=0 self.assertAlmostEqual(circle_area(1),pi) self.assertAlmostEqual(circle_area(0),0) self.assertAlmostEqual(circle_area(2.1),pi*2.1**2) ```

Where I'm getting tripped up is at 4:32 in the video, the instructor says to run the unit tests by opening a shell, going to the directory that contains both the circles and test_circles modules, and issuing the following command: python -m unittest test_circles.

Instructor's result (it runs the unit test):

``` Ran 1 test in 0.000s

OK ```

My result (it seems to execute circles.py itself):

[yo_scottie_oh@nobara Circles]$ python -m unittest test_circles Area of circles with r = 2 is 12.566370614359172. Area of circles with r = 0 is 0.0. Area of circles with r = -3 is 28.274333882308138. Area of circles with r = (2+5j) is (-65.97344572538566+62.83185307179586j). Area of circles with r = True is 3.141592653589793. Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "/usr/lib64/python3.11/unittest/__main__.py", line 18, in <module> main(module=None) File "/usr/lib64/python3.11/unittest/main.py", line 101, in __init__ self.parseArgs(argv) File "/usr/lib64/python3.11/unittest/main.py", line 150, in parseArgs self.createTests() File "/usr/lib64/python3.11/unittest/main.py", line 161, in createTests self.test = self.testLoader.loadTestsFromNames(self.testNames, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/unittest/loader.py", line 232, in loadTestsFromNames suites = [self.loadTestsFromName(name, module) for name in names] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/unittest/loader.py", line 232, in <listcomp> suites = [self.loadTestsFromName(name, module) for name in names] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/unittest/loader.py", line 162, in loadTestsFromName module = __import__(module_name) ^^^^^^^^^^^^^^^^^^^^^^^ File "/home/yo_scottie_oh/Projects/PythonTutorials/Socratica/Circles/test_circles.py", line 4, in <module> from circles import circle_area File "/home/yo_scottie_oh/Projects/PythonTutorials/Socratica/Circles/circles.py", line 14, in <module> A = circle_area(r) ^^^^^^^^^^^^^^ File "/home/yo_scottie_oh/Projects/PythonTutorials/Socratica/Circles/circles.py", line 6, in circle_area return pi*(r**2) ~^^~ TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int' [yo_scottie_oh@nobara Circles]$

I've been banging my head against the wall for hours now trying to figure out why when I execute the same command as the instructor, it appears to execute my Python scripts themselves instead of running the unit tests.

Other things I've tried:

I've read the Python documentation on unit testing. I tried adding this to the end of the test_circles.py document, but that did not change anything.

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

I've tried following this other written tutorial. After I create the text documents and organize them in the separate shapes and tests folders and run the command python -m unittest discover -v, again I get a different result from the author.

Author's result:

``` test_area (test_circle.TestCircle) ... ok test_circle_instance_of_shape (test_circle.TestCircle) ... ok test_create_circle_negative_radius (test_circle.TestCircle) ... ok test_area (test_square.TestSquare) ... ok test_create_square_negative_length (test_square.TestSquare) ... ok test_square_instance_of_shape (test_square.TestSquare) ... ok

---------------------------------------------------------------------- Ran 6 tests in 0.002s

OK ```

My result:

``` [yo_scottie_oh@nobara test]$ python -m unittest discover -v test_circle (unittest.loader._FailedTest.test_circle) ... ERROR test_square (unittest.loader._FailedTest.test_square) ... ERROR

====================================================================== ERROR: test_circle (unittest.loader._FailedTest.test_circle) ---------------------------------------------------------------------- ImportError: Failed to import test module: test_circle Traceback (most recent call last): File "/usr/lib64/python3.11/unittest/loader.py", line 419, in _find_test_path module = self._get_module_from_name(name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/unittest/loader.py", line 362, in _get_module_from_name import(name) File "/home/yo_scottie_oh/Projects/PythonTutorials/PythonUnitTesting/test/test_circle.py", line 4, in <module> from shapes.circle import Circle ModuleNotFoundError: No module named 'shapes'

====================================================================== ERROR: test_square (unittest.loader._FailedTest.test_square) ---------------------------------------------------------------------- ImportError: Failed to import test module: test_square Traceback (most recent call last): File "/usr/lib64/python3.11/unittest/loader.py", line 419, in _find_test_path module = self._get_module_from_name(name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/unittest/loader.py", line 362, in _get_module_from_name import(name) File "/home/yo_scottie_oh/Projects/PythonTutorials/PythonUnitTesting/test/test_square.py", line 3, in <module> from shapes.square import Square ModuleNotFoundError: No module named 'shapes'

---------------------------------------------------------------------- Ran 2 tests in 0.000s

FAILED (errors=2) ```

So yeah… this brings me to my question: What’s the obvious thing that everybody else gets that I'm missing? Is the tutorial outdated? Is it because the instructor is on Windows and I’m on Linux? Why won’t my unit tests run?

4

how to send the icecream output to a log file?

Hi, I'm currently using this to log my python process

logging.basicConfig(filename='filename.log', level=logging.DEBUG)

logger = logging.getLogger()

sys.stderr.write = logger.error

sys.stdout.write = logger.info

And then using print(f'{datetime.now()} log message') where I want to log.

It's working OK, buy I would like to live it to ic, but can't find any info on how to send the ic output to the logger.

Thanks for any help.

7

Is there any way to run a Python GTK3 apps on Windows?

Edit: The key was using msys2. After installing Gtk3 and PyGObject following the PyGObject guide for msys2 everything worked fine. Packaging with PyInstaller and nuitka was fine.

I've been developing an image halftoning app for a while using GTK on Linux, thinking GTK is cross platform, and delaying testing it on Windows for quite some time.

Today I decided to finally install Windows 10 (for the first time in more than a decade) on a separate machine and see what works and what does not.

For the past few hours I've been through hell trying to get GTK3 to work. I've followed multiple guides, none of which worked, including wingtk.

Furthermore, even if I successfully compile (or install) GTK, would it be possible to package it all up using something like PyInstaller or nuitka.

At this point I'm thinking of keeping the functions and writing a whole new GUI in Tk for the Windows port, as at least that seems to work.

Am I missing something?

9

How would you debug this script without creating many posts?

I won't know if this script works until I run it and see the errors but the comments won't start to generate until after all the posts so I can't debug that part until I've already created too much content.

```python import sqlite3 import requests from pythorhead import Lemmy import schedule import time import logging from config import *

logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s %(message)s", handlers=[logging.FileHandler("debug.log"), logging.StreamHandler()], )

def initialize_database(): conn = sqlite3.connect(DB_FILE) cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS posts ( github_url TEXT PRIMARY KEY, lemmy_post_id INTEGER, lemmy_post_name TEXT, lemmy_post_body TEXT ) """) cursor.execute(""" CREATE TABLE IF NOT EXISTS comments ( github_comment_id INTEGER PRIMARY KEY, lemmy_comment_id INTEGER, comment_user TEXT, comment_body TEXT ) """) conn.commit() return conn

def initialize_lemmy_instance(): lemmy = Lemmy(LEMMY_INSTANCE_URL) lemmy.log_in(LEMMY_USERNAME, LEMMY_PASSWORD) logging.info("Initialized Lemmy instance") return lemmy

def discover_community(lemmy, community_name): community_id = lemmy.discover_community(community_name) logging.info(f"Discovered community {community_name} with ID {community_id}") return community_id

def fetch_github_issues(repo): url = f"{GITHUB_API_BASE}/repos/{repo}/issues" headers = {"Accept": "application/vnd.github+json"} response = requests.get(url, headers=headers) logging.info(f"Fetched issues from {url}") return response.json()

def extract_issue_info(issue, repo): issue_url = issue["html_url"] issue_state = "[Closed]" if issue["state"] == "closed" else "" repo_abbr = "[BE]" if "lemmy" in repo else "[UI]" issue_title = f"{issue_state}{repo_abbr} {issue['title']} #{issue['number']}" issue_body = issue["body"] return issue_url, issue_title, issue_body

def post_issues_to_lemmy(lemmy, community_id, repo): conn = sqlite3.connect(DB_FILE) cursor = conn.cursor()

issues = fetch_github_issues(repo) for issue in issues: issue_url, issue_title, issue_body = extract_issue_info(issue, repo)

cursor.execute("SELECT lemmy_post_id FROM posts WHERE github_url=?", (issue_url,)) existing_post = cursor.fetchone()

if not existing_post: post = lemmy.post.create(community_id, issue_title, url=issue_url, body=issue_body)["post_view"]["post"] lemmy_post_id = post["id"] lemmy_post_name = post["name"] lemmy_post_body = post["body"] cursor.execute("INSERT INTO posts (github_url, lemmy_post_id, lemmy_post_name, lemmy_post_body) VALUES (?, ?, ?, ?)", (issue_url, lemmy_post_id, lemmy_post_name, lemmy_post_body)) conn.commit() logging.info(f"Posted issue {issue_title} to community {community_id}")

def fetch_github_comments(repo, issue_number): url = f"{GITHUB_API_BASE}/repos/{repo}/issues/{issue_number}/comments" headers = {"Accept": "application/vnd.github+json"} response = requests.get(url, headers=headers) logging.info(f"Fetched comments for issue #{issue_number}") return response.json()

def post_comments_to_lemmy(lemmy, post_id, repo, issue_number): conn = sqlite3.connect(DB_FILE) cursor = conn.cursor()

github_comments = fetch_github_comments(repo, issue_number) for comment in github_comments: github_comment_id = comment["id"] cursor.execute("SELECT lemmy_comment_id FROM comments WHERE github_comment_id=?", (github_comment_id,)) existing_comment = cursor.fetchone()

if not existing_comment: comment_user = comment["user"]["login"] comment_body = comment["body"] lemmy_comment_id = lemmy.comment.create(post_id, comment_body)["comment"]["id"]

cursor.execute("INSERT INTO comments (github_comment_id, lemmy_comment_id, comment_user, comment_body) VALUES (?, ?, ?, ?)", (github_comment_id, lemmy_comment_id, comment_user, comment_body)) conn.commit() logging.info(f"Posted comment {github_comment_id} to lemmy post {post_id}")

Fetch the GitHub issue number and Lemmy post ID for each issue

def fetch_issue_data(repo): conn = sqlite3.connect(DB_FILE) cursor = conn.cursor() cursor.execute("SELECT github_url, lemmy_post_id FROM posts WHERE github_url LIKE ?", (f"https://github.com/{repo}/issues/%",)) issue_data = cursor.fetchall() return issue_data

def extract_issue_number(github_url): return int(github_url.split("/")[-1])

def main(): logging.info("Running main function") initialize_database() lemmy = initialize_lemmy_instance() community_id = discover_community(lemmy, LEMMY_COMMUNITY_NAME) for repo in REPOSITORIES: post_issues_to_lemmy(lemmy, community_id, repo) issue_data = fetch_issue_data(repo) for github_url, lemmy_post_id in issue_data: issue_number = extract_issue_number post_comments_to_lemmy(lemmy, lemmy_post_id, repo, issue_number)

def run_periodically(): main() schedule.every(2).hours.do(main)

while True: schedule.run_pending() time.sleep(60)

if name == "main": logging.info("Starting script") run_periodically() ```

8

Help with spotipy

I am trying to create a playlist with spotify and the spotipy library in python. However, I keep getting a "No token provided" error when making my API request. However, if I use the same token with a curl request, it works! Can someone please help. This is my code:

``` auth_manager = SpotifyOAuth(client_id=CLIENT, client_secret=SECRET, redirect_uri="http://example.com/", scope=SCOPE, username=spotify_display_name ) token = auth_manager.get_access_token( as_dict=False, check_cache=True )

sp = spotipy.Spotify(auth_manager=auth_manager, auth=token ) user_dict = sp.current_user() user_id = user_dict["id"] print(f"Welcome, {user_dict['display_name']}")

SEARCH

QUERY FORMAT: "track: track-name year: YYYY"

spotify_search_endpoint = "https://api.spotify.com/v1/search/" test_query = "track:Hangin'+Tough year:1989"

search_parameters = { "q": format_query(test_query), "type": "track" }

results = sp.search(q=search_parameters["q"]) print(results) ```

output: {'tracks': {'href': 'https://api.spotify.com/v1/search?query=track%3AHangin%27%2BTough%2520year%3A1989&type=track&offset=0&limit=10', 'items': [], 'limit': 10, 'next': None, 'offset': 0, 'previous': None, 'total': 0}}

{ "error": { "status": 401, "message": "No token provided" } }

This is really frustrating! The authentication is working, otherwise the token wouldn't have been valid for the curl request. I must be doing something wrong with spotipy.

9