Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Test improvements #2131

Open
wants to merge 63 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
cd00035
Initial try to get python tests running on Github Actions
StopMotionCuber Oct 7, 2020
8cee18d
COLORS!!!
StopMotionCuber Oct 7, 2020
73a259f
I'd like to test my Github Actions improvements
StopMotionCuber Oct 7, 2020
c8f37bc
Install Powerline, so that tests can be found
StopMotionCuber Oct 7, 2020
1624b89
Try actions without tests/__init__.py
StopMotionCuber Oct 7, 2020
b661e84
Hack to include working dir in path
StopMotionCuber Oct 7, 2020
4aae113
Added conftest.py
StopMotionCuber Oct 7, 2020
5346c5d
Re-add __init__.py
StopMotionCuber Oct 7, 2020
31e63be
Add debugging test for lib
StopMotionCuber Oct 7, 2020
c2bc734
Verbose pytest
StopMotionCuber Oct 7, 2020
bdb4c2f
We only want to test for non-daemonic threads that are created
StopMotionCuber Oct 7, 2020
22a977e
Removed debug assert
StopMotionCuber Oct 7, 2020
1aaa362
Workaround to test the thread number with pytest
StopMotionCuber Oct 7, 2020
efc556c
Another approach to test the thread count with pytest
StopMotionCuber Oct 11, 2020
0ffce51
Add psutil which will modify some behaviour for getenv
StopMotionCuber Oct 11, 2020
0bf0804
Remove section for pre-psutil 2.0.0
StopMotionCuber Oct 11, 2020
5668c5e
`username()` should always be callable
StopMotionCuber Oct 11, 2020
dd6c29d
Don't do fail-fast, we want to see _all_ results
StopMotionCuber Oct 11, 2020
ed2eeaa
Increase sleep time to make GitHub Actions happy (...?)
StopMotionCuber Oct 11, 2020
1e1a16c
Don't cache username
StopMotionCuber Oct 11, 2020
4dc9d68
Fixed test which assumed the domain to be missing (introduced by cach…
StopMotionCuber Oct 11, 2020
6136f28
Also test mercurial + internal IP
StopMotionCuber Oct 11, 2020
e2480f9
Rename TestPowerline to PowerlineTest, as the `Test` prefix is reserv…
StopMotionCuber Oct 11, 2020
1135fbd
The duration / 0.2 should be greater, but don't take too much of a lo…
StopMotionCuber Oct 11, 2020
cb4bcef
Changed assert, as first and last update don't have a padding of 0.2 …
StopMotionCuber Oct 11, 2020
35acfd1
Don't validate formatter as we are using garbage formatter just as Po…
StopMotionCuber Oct 11, 2020
e636cb1
Update setFormatter, such that it is backwards compatible for Python …
StopMotionCuber Oct 11, 2020
e33e2fa
Remove deprecated stubs
StopMotionCuber Oct 11, 2020
24b4a89
Fixed some warnings raised by pytest
StopMotionCuber Oct 11, 2020
77297bd
Exchange imp for types as imp is deprecated
StopMotionCuber Oct 11, 2020
30a7696
Python 2 compatibility :/
StopMotionCuber Oct 11, 2020
e4ddc22
Less verbose output for tests
StopMotionCuber Oct 11, 2020
9838b90
Add tests from travis CI to Github Actions
StopMotionCuber Oct 11, 2020
c5c8a71
Initial try to transfer awesome tests to pytest
StopMotionCuber Oct 13, 2020
7b994f3
Add xprocess as dependency
StopMotionCuber Oct 13, 2020
ff2c521
Finished test conversion to pytest
StopMotionCuber Oct 13, 2020
3913572
Set env["LANG"] to make awesome tests reproducable
StopMotionCuber Oct 13, 2020
f380943
Changed address so that tests also work on macOS
StopMotionCuber Oct 15, 2020
1a080cd
Moved functions to root conftest to be usable for each module. As the…
StopMotionCuber Oct 15, 2020
f7d2369
Ported lemonbar tests, also removed socket from tests as this is not …
StopMotionCuber Oct 15, 2020
2da6b7e
Added conftest for python tests
StopMotionCuber Oct 15, 2020
dda6e35
Run all tests with pytest
StopMotionCuber Oct 15, 2020
bdda164
Restructured tests so that special conftest.py is only needed for tes…
StopMotionCuber Oct 15, 2020
76001a8
Cleanup for lemonbar tests
StopMotionCuber Oct 15, 2020
a79a2b1
Re-add socket for daemon
StopMotionCuber Oct 15, 2020
7e4c613
Added tests for daemon
StopMotionCuber Oct 15, 2020
a5dd92f
Fixed daemon tests
StopMotionCuber Oct 16, 2020
6cc0109
Added lint test
StopMotionCuber Oct 16, 2020
d93c425
Removed vterm tests as they are unused
StopMotionCuber Oct 21, 2020
51ec3b7
First attempts on pytest shell scripts
StopMotionCuber Oct 24, 2020
7ef2e19
Correct filenames
StopMotionCuber Oct 24, 2020
168fd16
Add some more dependencies
StopMotionCuber Oct 24, 2020
b1a3bad
Add sudo so that apt-get works
StopMotionCuber Oct 24, 2020
b61be1e
Added directory to PATH such that shell scripts can be found
StopMotionCuber Oct 24, 2020
da3e450
Correct escape_hl_start + end
StopMotionCuber Oct 24, 2020
2726898
Fixes to get more tests working
StopMotionCuber Oct 24, 2020
0c92319
Daemon tests
StopMotionCuber Oct 24, 2020
31acca5
Install socat for bash client
StopMotionCuber Oct 24, 2020
1016dfd
Skip Fish tests
StopMotionCuber Oct 26, 2020
6a43a7f
Removed zpython dependencies
StopMotionCuber Oct 29, 2020
acfef9b
Busybox exclusion + pdb subclass test
StopMotionCuber Oct 29, 2020
8ff6b4e
Finished first version of shell tests
StopMotionCuber Oct 30, 2020
813d054
Convert vim tests
StopMotionCuber Apr 5, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 38 additions & 3 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
name: Build and Publish to PyPI
name: Build, test and Publish to PyPI

on:
push:
branches:
- master
- develop
- feature/actions
- test_improvements
pull_request:
branches:
- develop
Expand All @@ -15,8 +16,9 @@ jobs:

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, 3.8]
python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9]

steps:
- name: Checkout code
Expand All @@ -30,13 +32,46 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel
pip install setuptools wheel pytest psutil hglib netifaces pytest-xprocess pexpect
sudo apt-get install -y tcsh zsh bash busybox fish mksh socat
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

- name: Build
run: |
python setup.py sdist bdist_wheel

- name: Install powerline
run: |
pip install .

- name: Run Python tests
run: |
python -m pytest --color=yes tests/test_python

- name: Run awesome tests
run: |
python -m pytest --color=yes tests/test_awesome

- name: Run lemonbar tests
run: |
python -m pytest --color=yes tests/test_bar

- name: Run daemon tests
run: |
python -m pytest --color=yes tests/test_daemon

- name: Run lint tests
run: |
python -m pytest --color=yes tests/test_lint

- name: Run shell tests
run: |
python -m pytest --color=yes tests/test_shells

- name: Run vim tests
run: |
python -m pytest --color=yes tests/test_vim

- name: Publish
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@master
Expand Down
6 changes: 5 additions & 1 deletion powerline/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,11 @@ def _set_log_handlers(common_config, logger, get_module_attr, stream=None):
except IndexError:
handler_format = common_config['log_format']
handler.setLevel(getattr(logging, handler_level_name))
handler.setFormatter(logging.Formatter(handler_format))
try:
handler.setFormatter(logging.Formatter(handler_format, validate=False))
except TypeError:
# the validate keyword is only supported from Python 3.8 onwards
handler.setFormatter(logging.Formatter(handler_format))
logger.addHandler(handler)
num_handlers += 1
if num_handlers == 0 and log_targets:
Expand Down
4 changes: 2 additions & 2 deletions powerline/renderers/shell/bash.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

class BashPromptRenderer(ShellRenderer):
'''Powerline bash prompt segment renderer.'''
escape_hl_start = '\['
escape_hl_end = '\]'
escape_hl_start = r'\['
escape_hl_end = r'\]'

character_translations = ShellRenderer.character_translations.copy()
character_translations[ord('$')] = '\\$'
Expand Down
15 changes: 3 additions & 12 deletions powerline/segments/common/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,8 @@ def __call__(self, pl, segment_info,
try:
import psutil

# psutil-2.0.0: psutil.Process.username is unbound method
if callable(psutil.Process.username):
def _get_user():
return psutil.Process(os.getpid()).username()
# pre psutil-2.0.0: psutil.Process.username has type property
else:
def _get_user():
return psutil.Process(os.getpid()).username
def _get_user():
return psutil.Process(os.getpid()).username()
except ImportError:
try:
import pwd
Expand All @@ -154,7 +148,6 @@ def _get_user():
return pwd.getpwuid(getuid()).pw_name


username = False
# os.geteuid is not available on windows
_geteuid = getattr(os, 'geteuid', lambda: 1)

Expand All @@ -172,14 +165,12 @@ def user(pl, segment_info, hide_user=None, hide_domain=False):

Highlight groups used: ``superuser`` or ``user``. It is recommended to define all highlight groups.
'''
global username
if (
segment_info['environ'].get('_POWERLINE_RUNNING_SHELL_TESTS')
== 'ee5bcdc6-b749-11e7-9456-50465d597777'
):
return 'user'
if username is False:
username = _get_user()
username = _get_user()
if username is None:
pl.warn('Failed to get username')
return None
Expand Down
2 changes: 1 addition & 1 deletion powerline/segments/common/mail.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def compute_state(self, key):
mail.login(key.username, key.password)
rc, message = mail.status(key.folder, '(UNSEEN)')
unread_str = message[0].decode('utf-8')
unread_count = int(re.search('UNSEEN (\d+)', unread_str).group(1))
unread_count = int(re.search(r'UNSEEN (\d+)', unread_str).group(1))
return unread_count

@staticmethod
Expand Down
3 changes: 3 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import pytest

pytest.register_assert_rewrite("tests.utils")
89 changes: 89 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import shutil
import time

import pytest
import os

from xprocess import ProcessStarter
from pathlib import Path

seekpos = 0


def __init__(self):
self.seekpos = 0


def start_daemon(xprocess, daemon, daemon_env):

class Starter(ProcessStarter):
env = daemon_env
pattern = ""
args = [daemon, "--socket", "/tmp/powerline-ipc-test-{}".format(os.getpid()), "--foreground"]

def wait(self, log_file):
time.sleep(0.5)
return True

xprocess.ensure("daemon", Starter)


def stop_daemon(xprocess):
cleanup_folder = xprocess.getinfo("daemon").controldir
xprocess.getinfo("daemon").terminate()
shutil.rmtree(cleanup_folder)


@pytest.fixture(scope="session")
def command():
return Path(os.path.abspath(os.path.dirname(__file__))).parent / "scripts" / "powerline"


@pytest.fixture(scope="session")
def daemon():
return Path(os.path.abspath(os.path.dirname(__file__))).parent / "scripts" / "powerline-daemon"


@pytest.fixture(scope="session")
def rootdir():
return Path(os.path.abspath(os.path.dirname(__file__))).parent


@pytest.fixture(scope="session")
def lemonbar_cmd():
return Path(os.path.abspath(os.path.dirname(__file__))).parent / \
"powerline" / "bindings" / "lemonbar" / "powerline-lemonbar.py"


@pytest.fixture(scope="module")
def daemon_process(xprocess, daemon, daemon_env):
global seekpos
seekpos = 0
start_daemon(xprocess, daemon, daemon_env)
yield
stop_daemon(xprocess)


@pytest.fixture(scope="function")
def print_daemon_logs(xprocess):
global seekpos
yield
with open(xprocess.getinfo("daemon").logpath) as fl:
fl.seek(seekpos)
print(fl.read())
seekpos = fl.tell()


# The following fixture is done that way, as importing from conftest is not really
# feasable, but the global seekpos needs to be known. Therefore, this function
# is imported via Dependency Injection
@pytest.fixture(scope="session")
def daemon_logs(xprocess):
def fun():
global seekpos
with open(xprocess.getinfo("daemon").logpath) as fl:
fl.seek(seekpos)
logs = fl.read()
return logs

return fun
25 changes: 13 additions & 12 deletions tests/modules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
import os

if sys.version_info < (2, 7):
from unittest2 import TestCase as _TestCase # NOQA
from unittest2 import TestCase as TestCase # NOQA
from unittest2 import main as _main # NOQA
from unittest2.case import SkipTest # NOQA
else:
from unittest import TestCase as _TestCase # NOQA
from unittest import TestCase as TestCase # NOQA
from unittest import main as _main # NOQA
from unittest.case import SkipTest # NOQA

Expand Down Expand Up @@ -50,16 +50,24 @@ def __exit__(self, exc_type, exc_value, traceback):
os.environ['POWERLINE_CURRENT_SUITE'] = self.saved_current_suite

def record_test_failure(self, fail_char, test_name, message, allow_failure=False):
try:
suite_obj = self.suite
except AttributeError:
suite_obj = "unknown"
if allow_failure:
fail_char = 'A' + fail_char
full_msg = '{fail_char} {suite}|{test_name} :: {message}'.format(
fail_char=fail_char,
suite=self.suite,
suite=suite_obj,
test_name=test_name,
message=message,
)
with open(os.environ['FAILURES_FILE'], 'a') as ffd:
ffd.write(full_msg + '\n')
try:
with open(os.environ['FAILURES_FILE'], 'a') as ffd:
ffd.write(full_msg + '\n')
except KeyError:
# Ignore writing to FAILURES_FILE if this is not defined in OS_ENVIRON
pass
return False

def exception(self, test_name, message, allow_failure=False):
Expand All @@ -85,10 +93,3 @@ def main(*args, **kwargs):
global suite
suite = PowerlineTestSuite(sys.argv[0])
_main(*args, **kwargs)


class TestCase(_TestCase):
def fail(self, msg=None):
suite.fail(self.__class__.__name__,
msg or 'Test failed without message')
super(TestCase, self).fail(*args, **kwargs)
15 changes: 6 additions & 9 deletions tests/modules/lib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)

import imp
import sys
import types


class Pl(object):
Expand Down Expand Up @@ -47,13 +47,6 @@ def urllib_read(query_url):

elif query_url.startswith('https://freegeoip.app/json/'):
return '{"ip":"82.145.55.16","country_code":"DE","country_name":"Germany","region_code":"NI","region_name":"Lower Saxony","city":"Meppen","zip_code":"49716","time_zone":"Europe/Berlin","latitude":52.6833,"longitude":7.3167,"metro_code":0}'
elif query_url.startswith('http://geoip.nekudo.com/api/'):
return '{"city":"Meppen","country":{"name":"Germany", "code":"DE"},"location":{"accuracy_radius":100,"latitude":52.6833,"longitude":7.3167,"time_zone":"Europe\/Berlin"},"ip":"82.145.55.16"}'
elif query_url.startswith('http://query.yahooapis.com/v1/public/'):
if 'Meppen' in query_url or '52.6833' in query_url:
return r'{"query":{"count":1,"created":"2016-05-13T19:43:18Z","lang":"en-US","results":{"channel":{"units":{"distance":"mi","pressure":"in","speed":"mph","temperature":"C"},"title":"Yahoo! Weather - Meppen, NI, DE","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/","description":"Yahoo! Weather for Meppen, NI, DE","language":"en-us","lastBuildDate":"Fri, 13 May 2016 09:43 PM CEST","ttl":"60","location":{"city":"Meppen","country":"Germany","region":" NI"},"wind":{"chill":"55","direction":"350","speed":"25"},"atmosphere":{"humidity":"57","pressure":"1004.0","rising":"0","visibility":"16.1"},"astronomy":{"sunrise":"5:35 am","sunset":"9:21 pm"},"image":{"title":"Yahoo! Weather","width":"142","height":"18","link":"http://weather.yahoo.com","url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"},"item":{"title":"Conditions for Meppen, NI, DE at 08:00 PM CEST","lat":"52.68993","long":"7.29115","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/","pubDate":"Fri, 13 May 2016 08:00 PM CEST","condition":{"code":"23","date":"Fri, 13 May 2016 08:00 PM CEST","temp":"14","text":"Breezy"},"forecast":[{"code":"30","date":"13 May 2016","day":"Fri","high":"71","low":"48","text":"Partly Cloudy"},{"code":"28","date":"14 May 2016","day":"Sat","high":"54","low":"44","text":"Mostly Cloudy"},{"code":"11","date":"15 May 2016","day":"Sun","high":"55","low":"43","text":"Showers"},{"code":"28","date":"16 May 2016","day":"Mon","high":"54","low":"42","text":"Mostly Cloudy"},{"code":"28","date":"17 May 2016","day":"Tue","high":"57","low":"43","text":"Mostly Cloudy"},{"code":"12","date":"18 May 2016","day":"Wed","high":"62","low":"45","text":"Rain"},{"code":"28","date":"19 May 2016","day":"Thu","high":"63","low":"48","text":"Mostly Cloudy"},{"code":"28","date":"20 May 2016","day":"Fri","high":"67","low":"50","text":"Mostly Cloudy"},{"code":"30","date":"21 May 2016","day":"Sat","high":"71","low":"50","text":"Partly Cloudy"},{"code":"30","date":"22 May 2016","day":"Sun","high":"74","low":"54","text":"Partly Cloudy"}],"description":"<![CDATA[<img src=\"http://l.yimg.com/a/i/us/we/52/23.gif\"/>\n<BR />\n<b>Current Conditions:</b>\n<BR />Breezy\n<BR />\n<BR />\n<b>Forecast:</b>\n<BR /> Fri - Partly Cloudy. High: 71Low: 48\n<BR /> Sat - Mostly Cloudy. High: 54Low: 44\n<BR /> Sun - Showers. High: 55Low: 43\n<BR /> Mon - Mostly Cloudy. High: 54Low: 42\n<BR /> Tue - Mostly Cloudy. High: 57Low: 43\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-674836/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n(provided by <a href=\"http://www.weather.com\" >The Weather Channel</a>)\n<BR />\n]]>","guid":{"isPermaLink":"false"}}}}}}'
elif 'Moscow' in query_url:
return r'{"query":{"count":1,"created":"2016-05-13T19:47:01Z","lang":"en-US","results":{"channel":{"units":{"distance":"mi","pressure":"in","speed":"mph","temperature":"C"},"title":"Yahoo! Weather - Moscow, Moscow Federal City, RU","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/","description":"Yahoo! Weather for Moscow, Moscow Federal City, RU","language":"en-us","lastBuildDate":"Fri, 13 May 2016 10:47 PM MSK","ttl":"60","location":{"city":"Moscow","country":"Russia","region":" Moscow Federal City"},"wind":{"chill":"45","direction":"80","speed":"11"},"atmosphere":{"humidity":"52","pressure":"993.0","rising":"0","visibility":"16.1"},"astronomy":{"sunrise":"4:19 am","sunset":"8:34 pm"},"image":{"title":"Yahoo! Weather","width":"142","height":"18","link":"http://weather.yahoo.com","url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"},"item":{"title":"Conditions for Moscow, Moscow Federal City, RU at 09:00 PM MSK","lat":"55.741638","long":"37.605061","link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/","pubDate":"Fri, 13 May 2016 09:00 PM MSK","condition":{"code":"33","date":"Fri, 13 May 2016 09:00 PM MSK","temp":"9","text":"Mostly Clear"},"forecast":[{"code":"30","date":"13 May 2016","day":"Fri","high":"62","low":"41","text":"Partly Cloudy"},{"code":"30","date":"14 May 2016","day":"Sat","high":"64","low":"43","text":"Partly Cloudy"},{"code":"30","date":"15 May 2016","day":"Sun","high":"63","low":"44","text":"Partly Cloudy"},{"code":"12","date":"16 May 2016","day":"Mon","high":"60","low":"47","text":"Rain"},{"code":"12","date":"17 May 2016","day":"Tue","high":"64","low":"48","text":"Rain"},{"code":"28","date":"18 May 2016","day":"Wed","high":"67","low":"48","text":"Mostly Cloudy"},{"code":"12","date":"19 May 2016","day":"Thu","high":"68","low":"49","text":"Rain"},{"code":"39","date":"20 May 2016","day":"Fri","high":"66","low":"50","text":"Scattered Showers"},{"code":"39","date":"21 May 2016","day":"Sat","high":"69","low":"49","text":"Scattered Showers"},{"code":"30","date":"22 May 2016","day":"Sun","high":"73","low":"50","text":"Partly Cloudy"}],"description":"<![CDATA[<img src=\"http://l.yimg.com/a/i/us/we/52/33.gif\"/>\n<BR />\n<b>Current Conditions:</b>\n<BR />Mostly Clear\n<BR />\n<BR />\n<b>Forecast:</b>\n<BR /> Fri - Partly Cloudy. High: 62Low: 41\n<BR /> Sat - Partly Cloudy. High: 64Low: 43\n<BR /> Sun - Partly Cloudy. High: 63Low: 44\n<BR /> Mon - Rain. High: 60Low: 47\n<BR /> Tue - Rain. High: 64Low: 48\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n(provided by <a href=\"http://www.weather.com\" >The Weather Channel</a>)\n<BR />\n]]>","guid":{"isPermaLink":"false"}}}}}}'
elif query_url.startswith('https://api.openweathermap.org/data/2.5/'):
if 'Meppen' in query_url or '52.6833' in query_url:
return r'{"coord":{"lon":7.29,"lat":52.69},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"base":"stations","main":{"temp":293.15,"feels_like":295.16,"temp_min":293.15,"temp_max":295.37,"pressure":1018,"humidity":77},"visibility":10000,"wind":{"speed":1.12,"deg":126},"clouds":{"all":0},"dt":1600196220,"sys":{"type":1,"id":1871,"country":"DE","sunrise":1600146332,"sunset":1600191996},"timezone":7200,"id":2871845,"name":"Meppen","cod":200}'
Expand Down Expand Up @@ -100,7 +93,11 @@ def replace_module(name, new=None, **kwargs):


def new_module(name, **kwargs):
module = imp.new_module(name)
try:
module = types.ModuleType(name)
except TypeError:
import imp
module = imp.new_module(name)
for k, v in kwargs.items():
setattr(module, k, v)
return module
Expand Down
20 changes: 20 additions & 0 deletions tests/test_awesome/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import os
import pytest


# This is placed here as autouse, such that daemon process is actually used for all tests in this module
# This is done so that the daemon does not need to be run for each test, and therefore
# daemon_env only needs to be defined when the daemon is actually used
@pytest.fixture(scope="module", autouse=True)
def autouse_daemon(daemon_process):
yield daemon_process


@pytest.fixture(scope="module")
def daemon_env():
env = os.environ.copy()
env["XDG_CONFIG_HOME"] = os.path.abspath(os.path.dirname(__file__))
env["LANG"] = "C"
env["PATH"] = "{}:{}".format(os.path.join(os.path.abspath(os.path.dirname(__file__)), "path"), env["PATH"])
return env

5 changes: 3 additions & 2 deletions tests/test_awesome/path/awesome-client
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/bin/sh
echo "$@" >> "$TEST_ROOT/results/args"
cat >> "$TEST_ROOT/results/requests"
mkdir -p results
echo "$@" >> "results/args"
cat >> "results/requests"
38 changes: 38 additions & 0 deletions tests/test_awesome/test_awesome.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import subprocess
import os
import time

from tests.utils import logs_empty


def test_wm_awesome(command, daemon_env):
time.sleep(2)
for _ in range(5):
output = subprocess.run(
[command, "--socket", "/tmp/powerline-ipc-test-{}".format(os.getpid()), "wm.awesome"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=daemon_env)
logs_empty(output)


def test_kill_log(daemon, daemon_logs, daemon_env):
time.sleep(5)
output = subprocess.run(
[daemon, "--socket", "/tmp/powerline-ipc-test-{}".format(os.getpid()), "--quiet", "--kill"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=daemon_env)
logs_empty(output)
logs = daemon_logs()
assert logs == ""


def test_check_awesome_logs(xprocess):
results_dir = xprocess.getinfo("daemon").controldir / "results"
with open(results_dir / "requests") as requests_file:
content = requests_file.read()
content_split = content.splitlines()
line_count = len(content_split)
assert 5 <= line_count <= 15
for line in content_split:
assert line == \
"powerline_widget:set_markup('<span foreground=\"#303030\">" \
" </span><span foreground=\"#d0d0d0\" background=\"#303030\" " \
"font_weight=\"bold\"> default-right </span>')"