Skip to content

Commit

Permalink
Initial pytest setup (make-all#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicole-ashley authored May 24, 2020
1 parent 5f25652 commit 25efc86
Show file tree
Hide file tree
Showing 22 changed files with 210 additions and 29 deletions.
6 changes: 6 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[run]
branch = True

[report]
skip_empty = True
include = custom_components/*
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"files.exclude": {
"config/custom_components/goldair_climate": true
},
"python.pythonPath": "/usr/local/bin/python",
"python.pythonPath": "/usr/bin/python",
"terminal.integrated.shell.linux": "/bin/bash"
},
"mounts": [
Expand Down
11 changes: 5 additions & 6 deletions .github/workflows/hacs-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ name: Validate with HACS

on:
push:
pull_request:
schedule:
- cron: "0 0 * * *"
- cron: '0 0 * * *'

jobs:
validate:
runs-on: "ubuntu-latest"
runs-on: 'ubuntu-latest'
steps:
- uses: "actions/checkout@v2"
- uses: 'actions/checkout@v2'
- name: HACS validation
uses: "hacs/integration/action@master"
uses: 'hacs/integration/action@master'
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CATEGORY: "integration"
CATEGORY: 'integration'
7 changes: 3 additions & 4 deletions .github/workflows/hassfest-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ name: Validate with hassfest

on:
push:
pull_request:
schedule:
- cron: "0 0 * * *"
- cron: '0 0 * * *'

jobs:
validate:
runs-on: "ubuntu-latest"
runs-on: 'ubuntu-latest'
steps:
- uses: "actions/checkout@v2"
- uses: 'actions/checkout@v2'
- uses: home-assistant/actions/hassfest@master
6 changes: 4 additions & 2 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Linting

on: [push, pull_request]
on: push

jobs:
lint:
Expand All @@ -14,7 +14,9 @@ jobs:
python-version: 3.7

- name: Install dependencies
run: pip install --pre -r requirements.txt
run: |
pip install -r requirements-first.txt
pip install --pre -r requirements-dev.txt
- name: isort
run: isort --recursive --diff
- name: Black
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Python tests

on: push

jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8]

steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-first.txt
pip install -r requirements-dev.txt
- name: Test with pytest
run: pytest --cov=. --cov-config=.coveragerc --cov-report xml:coverage.xml
- name: Track master branch
run: git fetch --no-tags https://$GITHUB_ACTOR:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY +refs/heads/master:refs/remotes/origin/master
- name: SonarCloud scan
uses: sonarsource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
/.vscode/
__pycache__/
/config/
*.zip
*.zip
/.coverage
/coverage.xml
2 changes: 1 addition & 1 deletion custom_components/goldair_climate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
CONF_TYPE,
CONF_TYPE_DEHUMIDIFIER,
CONF_TYPE_FAN,
CONF_TYPE_HEATER,
CONF_TYPE_GPPH_HEATER,
SCAN_INTERVAL,
CONF_TYPE_AUTO,
)
Expand Down
4 changes: 2 additions & 2 deletions custom_components/goldair_climate/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
CONF_TYPE_FAN,
CONF_TYPE_GECO_HEATER,
CONF_TYPE_GPCV_HEATER,
CONF_TYPE_HEATER,
CONF_TYPE_GPPH_HEATER,
CONF_CLIMATE,
CONF_TYPE_AUTO,
)
Expand All @@ -31,7 +31,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
if discovery_info[CONF_TYPE] is None:
raise ValueError(f"Unable to detect type for device {device.name}")

if discovery_info[CONF_TYPE] == CONF_TYPE_HEATER:
if discovery_info[CONF_TYPE] == CONF_TYPE_GPPH_HEATER:
data[CONF_CLIMATE] = GoldairHeater(device)
elif discovery_info[CONF_TYPE] == CONF_TYPE_DEHUMIDIFIER:
data[CONF_CLIMATE] = GoldairDehumidifier(device)
Expand Down
4 changes: 2 additions & 2 deletions custom_components/goldair_climate/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
CONF_DEVICE_ID,
CONF_LOCAL_KEY,
CONF_TYPE,
CONF_TYPE_HEATER,
CONF_TYPE_GPPH_HEATER,
CONF_TYPE_DEHUMIDIFIER,
CONF_TYPE_FAN,
CONF_TYPE_GECO_HEATER,
Expand All @@ -26,7 +26,7 @@
"type": vol.In(
[
CONF_TYPE_AUTO,
CONF_TYPE_HEATER,
CONF_TYPE_GPPH_HEATER,
CONF_TYPE_DEHUMIDIFIER,
CONF_TYPE_FAN,
CONF_TYPE_GECO_HEATER,
Expand Down
2 changes: 1 addition & 1 deletion custom_components/goldair_climate/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
CONF_LOCAL_KEY = "local_key"
CONF_TYPE = "type"
CONF_TYPE_AUTO = "auto"
CONF_TYPE_HEATER = "heater"
CONF_TYPE_GPPH_HEATER = "heater"
CONF_TYPE_DEHUMIDIFIER = "dehumidifier"
CONF_TYPE_FAN = "fan"
CONF_TYPE_GPCV_HEATER = "gpcv_heater"
Expand Down
4 changes: 2 additions & 2 deletions custom_components/goldair_climate/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
CONF_TYPE_FAN,
CONF_TYPE_GECO_HEATER,
CONF_TYPE_GPCV_HEATER,
CONF_TYPE_HEATER,
CONF_TYPE_GPPH_HEATER,
)

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -91,7 +91,7 @@ async def async_inferred_type(self):
if "8" in cached_state:
return CONF_TYPE_FAN
if "106" in cached_state:
return CONF_TYPE_HEATER
return CONF_TYPE_GPPH_HEATER
if "7" in cached_state:
return CONF_TYPE_GPCV_HEATER
if "3" in cached_state:
Expand Down
4 changes: 2 additions & 2 deletions custom_components/goldair_climate/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
CONF_TYPE_FAN,
CONF_TYPE_GECO_HEATER,
CONF_TYPE_GPCV_HEATER,
CONF_TYPE_HEATER,
CONF_TYPE_GPPH_HEATER,
CONF_DISPLAY_LIGHT,
CONF_TYPE_AUTO,
)
Expand All @@ -29,7 +29,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
if discovery_info[CONF_TYPE] is None:
raise ValueError(f"Unable to detect type for device {device.name}")

if discovery_info[CONF_TYPE] == CONF_TYPE_HEATER:
if discovery_info[CONF_TYPE] == CONF_TYPE_GPPH_HEATER:
data[CONF_DISPLAY_LIGHT] = GoldairHeaterLedDisplayLight(device)
elif discovery_info[CONF_TYPE] == CONF_TYPE_DEHUMIDIFIER:
data[CONF_DISPLAY_LIGHT] = GoldairDehumidifierLedDisplayLight(device)
Expand Down
4 changes: 2 additions & 2 deletions custom_components/goldair_climate/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
CONF_TYPE_FAN,
CONF_TYPE_GECO_HEATER,
CONF_TYPE_GPCV_HEATER,
CONF_TYPE_HEATER,
CONF_TYPE_GPPH_HEATER,
CONF_CHILD_LOCK,
CONF_TYPE_AUTO,
)
Expand All @@ -34,7 +34,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
if discovery_info[CONF_TYPE] is None:
raise ValueError(f"Unable to detect type for device {device.name}")

if discovery_info[CONF_TYPE] == CONF_TYPE_HEATER:
if discovery_info[CONF_TYPE] == CONF_TYPE_GPPH_HEATER:
data[CONF_CHILD_LOCK] = GoldairHeaterChildLock(device)
elif discovery_info[CONF_TYPE] == CONF_TYPE_DEHUMIDIFIER:
data[CONF_CHILD_LOCK] = GoldairDehumidifierChildLock(device)
Expand Down
2 changes: 1 addition & 1 deletion custom_components/goldair_climate/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
"documentation": "https://github.com/nikrolls/homeassistant-goldair-climate",
"dependencies": [],
"codeowners": ["@nikrolls"],
"requirements": ["pytuya>=7.0.5"],
"requirements": ["pycrypto~=2.6.1", "pytuya~=7.0.5"],
"config_flow": true
}
7 changes: 7 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
homeassistant~=0.110.1
pycrypto~=2.6.1
pytuya~=7.0.5
pytest~=5.4.2
pytest-cov~=2.9.0
black~=19.10b0
isort~=4.3.21
1 change: 1 addition & 0 deletions requirements-first.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pycrypto~=2.6.1
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
black==19.*
isort==4.*
pycrypto~=2.6.1
pytuya~=7.0.5
6 changes: 6 additions & 0 deletions sonar-project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
sonar.organization=nikrolls
sonar.projectKey=nikrolls_homeassistant-goldair-climate

sonar.sources=./custom_components/goldair_climate
sonar.tests=./tests
sonar.python.coverage.reportPaths=/github/workspace/coverage.xml
Empty file added tests/__init__.py
Empty file.
44 changes: 44 additions & 0 deletions tests/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
GPPH_HEATER_PAYLOAD = {
"1": False,
"2": 25,
"3": 17,
"4": "C",
"6": True,
"12": 0,
"101": "5",
"102": 0,
"103": False,
"104": True,
"105": "auto",
"106": 20,
}

GPCV_HEATER_PAYLOAD = {
"1": True,
"2": True,
"3": 30,
"4": 25,
"5": 0,
"6": 0,
"7": "Low",
}

GECO_HEATER_PAYLOAD = {"1": True, "2": True, "3": 30, "4": 25, "5": 0, "6": 0}

DEHUMIDIFIER_PAYLOAD = {
"1": False,
"2": "0",
"4": 30,
"5": False,
"6": "1",
"7": False,
"11": 0,
"12": "0",
"101": False,
"102": False,
"103": 20,
"104": 78,
"105": False,
}

FAN_PAYLOAD = {"1": False, "2": "12", "3": "normal", "8": True, "11": "0", "101": False}
82 changes: 82 additions & 0 deletions tests/test_device.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from unittest import IsolatedAsyncioTestCase
from unittest.mock import patch

from custom_components.goldair_climate.const import (
CONF_TYPE_DEHUMIDIFIER,
CONF_TYPE_FAN,
CONF_TYPE_GECO_HEATER,
CONF_TYPE_GPCV_HEATER,
CONF_TYPE_GPPH_HEATER,
)
from custom_components.goldair_climate.device import GoldairTuyaDevice

from .const import (
DEHUMIDIFIER_PAYLOAD,
FAN_PAYLOAD,
GECO_HEATER_PAYLOAD,
GPCV_HEATER_PAYLOAD,
GPPH_HEATER_PAYLOAD,
)


class TestDevice(IsolatedAsyncioTestCase):
def setUp(self):
patcher = patch("pytuya.Device")
self.addCleanup(patcher.stop)
self.mock_api = patcher.start()
self.subject = GoldairTuyaDevice(
"Some name", "some_dev_id", "some.ip.address", "some_local_key", None
)

def test_configures_pytuya_correctly(self):
self.mock_api.assert_called_once_with(
"some_dev_id", "some.ip.address", "some_local_key", "device"
)
self.assertIs(self.subject._api, self.mock_api())

def test_name(self):
"""Returns the name given at instantiation."""
self.assertEqual("Some name", self.subject.name)

def test_unique_id(self):
"""Returns the unique ID presented by the API class."""
self.assertIs(self.subject.unique_id, self.mock_api().id)

def test_device_info(self):
"""Returns generic info plus the unique ID for categorisation."""
self.assertEqual(
self.subject.device_info,
{
"identifiers": {("goldair_climate", self.mock_api().id)},
"name": "Some name",
"manufacturer": "Goldair",
},
)

async def test_detects_geco_heater_payload(self):
self.subject._cached_state = GECO_HEATER_PAYLOAD
self.assertEqual(
await self.subject.async_inferred_type(), CONF_TYPE_GECO_HEATER
)

async def test_detects_gpcv_heater_payload(self):
self.subject._cached_state = GPCV_HEATER_PAYLOAD
self.assertEqual(
await self.subject.async_inferred_type(), CONF_TYPE_GPCV_HEATER
)

async def test_detects_gpph_heater_payload(self):
self.subject._cached_state = GPPH_HEATER_PAYLOAD
self.assertEqual(
await self.subject.async_inferred_type(), CONF_TYPE_GPPH_HEATER
)

async def test_detects_dehumidifier_payload(self):
self.subject._cached_state = DEHUMIDIFIER_PAYLOAD
self.assertEqual(
await self.subject.async_inferred_type(), CONF_TYPE_DEHUMIDIFIER
)

async def test_detects_fan_payload(self):
self.subject._cached_state = FAN_PAYLOAD
self.assertEqual(await self.subject.async_inferred_type(), CONF_TYPE_FAN)

0 comments on commit 25efc86

Please sign in to comment.