Skip to content

Commit

Permalink
Initial unit testing
Browse files Browse the repository at this point in the history
  • Loading branch information
d0ugal committed Sep 7, 2018
1 parent ce39c6e commit b9a8f60
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 31 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.tox
__pycache__
.pytest_cache
.coverage
56 changes: 35 additions & 21 deletions dropbox-upload/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
import pathlib
import sys

import requests

import arrow
import dropbox
import requests
import retrace
from dropbox import exceptions

Expand All @@ -30,6 +31,8 @@ def setup_logging(config):
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
ch.setFormatter(formatter)
# Remove existing handlers. This should be an issue in unit tests.
log.handlers = []
log.addHandler(ch)
return log

Expand All @@ -45,9 +48,11 @@ def bytes_to_human(nbytes):


def hassio_get(path):
r = requests.get(f"http://hassio/{path}", headers=AUTH_HEADERS).json()
LOG.debug(r)
return r["data"]
r = requests.get(f"http://hassio/{path}", headers=AUTH_HEADERS)
r.raise_for_status()
j = r.json()
LOG.debug(j)
return j["data"]


def list_snapshots():
Expand Down Expand Up @@ -135,9 +140,27 @@ def file_exists(dbx, file_path, dest_path):
return False


def main():
def process_snapshot(dropbox_dir, dbx, snapshot):
path = local_path(snapshot)
created = arrow.get(snapshot["date"])
size = bytes_to_human(os.path.getsize(path))
target = str(dropbox_path(dropbox_dir, snapshot))
LOG.info(f"Slug: {snapshot['slug']}")
LOG.info(f"Created: {created}")
LOG.info(f"Size: {size}")
LOG.info(f"Uploading to: {target}")
try:
if file_exists(dbx, path, target):
LOG.info("Already found in Dropbox with the same hash")
return
upload_file(dbx, path, target)
except Exception:
LOG.exception("Upload failed")


config = load_config()
def main(config_file):

config = load_config(config_file)
setup_logging(config)
dropbox_dir = pathlib.Path(config["dropbox_dir"])

Expand All @@ -146,29 +169,20 @@ def main():
LOG.info(f"Backing up {len(snapshots)} snapshots")
LOG.info(f"Backing up to Dropbox directory: {dropbox_dir}")

if not snapshots:
LOG.warning("No snapshots found to backup")
return

dbx = dropbox.Dropbox(config["access_token"])
try:
dbx.users_get_current_account()
except exceptions.AuthError:
LOG.error("Invalid access token")
return

for i, snapshot in enumerate(snapshots, start=1):
path = local_path(snapshot)
created = arrow.get(snapshot["date"])
size = bytes_to_human(os.path.getsize(path))
target = str(dropbox_path(dropbox_dir, snapshot))
LOG.info(f"Snapshot: {snapshot['name']} ({i}/{len(snapshots)})")
LOG.info(f"Slug: {snapshot['slug']}")
LOG.info(f"Created: {created}")
LOG.info(f"Size: {size}")
LOG.info(f"Uploading to: {target}")
try:
if file_exists(dbx, path, target):
LOG.info("Already found in Dropbox with the same hash")
continue
upload_file(dbx, path, target)
except Exception:
LOG.exception("Upload failed")
process_snapshot(dropbox_dir, dbx, snapshot)

LOG.info("Uploads complete")

Expand Down
6 changes: 6 additions & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
black
isort
pyflakes
pytest
pytest-cov
requests-mock
112 changes: 111 additions & 1 deletion tests/test_dropbox_upload.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,115 @@
import json
import logging
import pathlib

import upload
from dropbox import exceptions

def test_bytes_to_human():

def test_bytes_to_human():
assert upload.bytes_to_human(1024) == "1 KB"


def test_compute_dropbox_hash(tmpdir):
p = tmpdir.join("fake-snapshot.txt")
p.write("fake content")
assert upload.compute_dropbox_hash(p.strpath).startswith("de92bfc3d2")


def test_load_config(tmpdir):
p = tmpdir.join("config.json")
p.write(json.dumps({}))
assert upload.load_config(p.strpath) == {}


def test_local_path():
expected = pathlib.Path("/backup/SLUG.tar")
assert upload.local_path({"slug": "SLUG"}) == expected


def test_dropbox_path():
dropbox_dir = pathlib.Path("/dropbox_dir/")
expected = pathlib.Path("/dropbox_dir/SLUG.tar")
assert upload.dropbox_path(dropbox_dir, {"slug": "SLUG"}) == expected


def test_setup_logging_normal():
logger = upload.setup_logging({})
assert logger.level == logging.INFO


def test_setup_logging_debug():
logger = upload.setup_logging({"debug": True})
assert logger.level == logging.DEBUG


def test_hassio_api(requests_mock):
requests_mock.get("http://hassio/snapshots", text=json.dumps({"data": {}}))
assert upload.hassio_get("snapshots") == {}


def test_list_snapshots(requests_mock):
data = {"data": {"snapshots": []}}
requests_mock.get("http://hassio/snapshots", text=json.dumps(data))
assert upload.list_snapshots() == []


def test_main_no_snapshots(tmpdir, requests_mock, caplog):

# Create config file
p = tmpdir.join("config.json")
p.write(json.dumps({"dropbox_dir": "snapshots", "access_token": "token"}))

# Mock hassio
data = {"data": {"snapshots": []}}
requests_mock.get("http://hassio/snapshots", text=json.dumps(data))

upload.main(p.strpath)

assert (
"docker_upload",
logging.WARNING,
"No snapshots found to backup",
) in caplog.record_tuples


def test_main_invalid_token(tmpdir, requests_mock, caplog):

# Create config file
p = tmpdir.join("config.json")
p.write(json.dumps({"dropbox_dir": "snapshots", "access_token": "token"}))

# Mock hassio
data = {
"data": {
"snapshots": [
{
"slug": "ce27de75",
"name": "Automated Backup 2018-09-05",
"date": "2018-09-05T01:00:00.171676+00:00",
"type": "full",
"protected": False,
}
]
}
}
requests_mock.get("http://hassio/snapshots", text=json.dumps(data))

requests_mock.post(
"https://api.dropboxapi.com/2/users/get_current_account",
exc=exceptions.AuthError("Request ID", "Invalid token"),
)

assert (
"docker_upload",
logging.WARNING,
"No snapshots found to backup",
) not in caplog.record_tuples

upload.main(p.strpath)

assert (
"docker_upload",
logging.ERROR,
"Invalid access token",
) in caplog.record_tuples
18 changes: 9 additions & 9 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,24 @@ setenv = PYTHONPATH = {toxinidir}/dropbox-upload
changedir=tests
deps =
-rdropbox-upload/requirements.txt
pytest
commands= pytest --basetemp={envtmpdir} {posargs}
-rtest-requirements.txt
commands=
pytest --basetemp={envtmpdir} \
--cov=upload --cov-fail-under=60 --cov-report=term-missing {posargs}

[testenv:format]
basepython=python3
deps = black
commands=black {toxinidir}/dropbox-upload
commands=black {toxinidir}

[testenv:lint]
basepython=python3
deps =
black
pyflakes
isort
-rtest-requirements.txt
commands=
pyflakes {toxinidir}/dropbox-upload
black --check {toxinidir}/dropbox-upload
isort --check-only --diff --recursive {toxinidir}/dropbox-upload
pyflakes {toxinidir}/dropbox-upload {toxinidir}/tests
black --check {toxinidir}/dropbox-upload {toxinidir}/tests
isort --check-only --diff --recursive {toxinidir}/dropbox-upload {toxinidir}/tests

[testenv:docker-build]
passenv=
Expand Down

0 comments on commit b9a8f60

Please sign in to comment.