|
2 | 2 | test iotools for PSM3
|
3 | 3 | """
|
4 | 4 |
|
| 5 | +import os |
5 | 6 | from pvlib.iotools import psm3
|
6 | 7 | from conftest import needs_pandas_0_22, DATA_DIR
|
7 | 8 | import numpy as np
|
8 | 9 | import pandas as pd
|
9 | 10 | import pytest
|
10 | 11 | from requests import HTTPError
|
11 | 12 | from io import StringIO
|
| 13 | +import warnings |
12 | 14 |
|
13 | 15 | TMY_TEST_DATA = DATA_DIR / 'test_psm3_tmy-2017.csv'
|
14 | 16 | YEAR_TEST_DATA = DATA_DIR / 'test_psm3_2017.csv'
|
|
21 | 23 | 'Temperature Units', 'Pressure Units', 'Wind Direction Units',
|
22 | 24 | 'Wind Speed', 'Surface Albedo Units', 'Version']
|
23 | 25 |
|
24 |
| -DEMO_KEY = 'DEMO_KEY' |
| 26 | + |
| 27 | + |
| 28 | +@pytest.fixture(scope="module") |
| 29 | +def nrel_api_key(): |
| 30 | + """Supplies pvlib-python's NREL Developer Network API key. |
| 31 | +
|
| 32 | + Azure Pipelines CI utilizes a secret variable set to NREL_API_KEY |
| 33 | + to mitigate failures associated with using the default key of |
| 34 | + "DEMO_KEY". A user is capable of using their own key this way if |
| 35 | + desired however the default key should suffice for testing purposes. |
| 36 | + """ |
| 37 | + try: |
| 38 | + demo_key = os.environ["NREL_API_KEY"] |
| 39 | + except KeyError: |
| 40 | + warnings.warn( |
| 41 | + "WARNING: NREL API KEY environment variable not set! " |
| 42 | + "Using DEMO_KEY instead. Unexpected failures may occur." |
| 43 | + ) |
| 44 | + demo_key = 'DEMO_KEY' |
| 45 | + return demo_key |
25 | 46 |
|
26 | 47 |
|
27 | 48 | def assert_psm3_equal(header, data, expected):
|
@@ -50,47 +71,58 @@ def assert_psm3_equal(header, data, expected):
|
50 | 71 |
|
51 | 72 |
|
52 | 73 | @needs_pandas_0_22
|
53 |
| -def test_get_psm3_tmy(): |
| 74 | +@pytest.mark.flaky(reruns=5, reruns_delay=2) |
| 75 | +def test_get_psm3_tmy(nrel_api_key): |
54 | 76 | """test get_psm3 with a TMY"""
|
55 |
| - header, data = psm3.get_psm3(LATITUDE, LONGITUDE, DEMO_KEY, PVLIB_EMAIL, |
56 |
| - names='tmy-2017') |
| 77 | + header, data = psm3.get_psm3(LATITUDE, LONGITUDE, nrel_api_key, |
| 78 | + PVLIB_EMAIL, names='tmy-2017') |
57 | 79 | expected = pd.read_csv(TMY_TEST_DATA)
|
58 | 80 | assert_psm3_equal(header, data, expected)
|
59 |
| - # check errors |
60 |
| - with pytest.raises(HTTPError): |
61 |
| - # HTTP 403 forbidden because api_key is rejected |
62 |
| - psm3.get_psm3(LATITUDE, LONGITUDE, api_key='BAD', email=PVLIB_EMAIL) |
63 |
| - with pytest.raises(HTTPError): |
64 |
| - # coordinates were not found in the NSRDB |
65 |
| - psm3.get_psm3(51, -5, DEMO_KEY, PVLIB_EMAIL) |
66 |
| - with pytest.raises(HTTPError): |
67 |
| - # names is not one of the available options |
68 |
| - psm3.get_psm3(LATITUDE, LONGITUDE, DEMO_KEY, PVLIB_EMAIL, names='bad') |
69 | 81 |
|
70 | 82 |
|
71 | 83 | @needs_pandas_0_22
|
72 |
| -def test_get_psm3_singleyear(): |
| 84 | +@pytest.mark.flaky(reruns=5, reruns_delay=2) |
| 85 | +def test_get_psm3_singleyear(nrel_api_key): |
73 | 86 | """test get_psm3 with a single year"""
|
74 |
| - header, data = psm3.get_psm3(LATITUDE, LONGITUDE, DEMO_KEY, PVLIB_EMAIL, |
75 |
| - names='2017', interval=30) |
| 87 | + header, data = psm3.get_psm3(LATITUDE, LONGITUDE, nrel_api_key, |
| 88 | + PVLIB_EMAIL, names='2017', interval=30) |
76 | 89 | expected = pd.read_csv(YEAR_TEST_DATA)
|
77 | 90 | assert_psm3_equal(header, data, expected)
|
78 |
| - # check leap day |
79 |
| - _, data_2012 = psm3.get_psm3(LATITUDE, LONGITUDE, DEMO_KEY, PVLIB_EMAIL, |
80 |
| - names='2012', interval=60, leap_day=True) |
81 |
| - assert len(data_2012) == (8760+24) |
82 |
| - # check errors |
83 |
| - with pytest.raises(HTTPError): |
84 |
| - # HTTP 403 forbidden because api_key is rejected |
85 |
| - psm3.get_psm3(LATITUDE, LONGITUDE, api_key='BAD', email=PVLIB_EMAIL, |
86 |
| - names='2017') |
87 |
| - with pytest.raises(HTTPError): |
88 |
| - # coordinates were not found in the NSRDB |
89 |
| - psm3.get_psm3(51, -5, DEMO_KEY, PVLIB_EMAIL, names='2017') |
90 |
| - with pytest.raises(HTTPError): |
91 |
| - # intervals can only be 30 or 60 minutes |
92 |
| - psm3.get_psm3(LATITUDE, LONGITUDE, DEMO_KEY, PVLIB_EMAIL, names='2017', |
93 |
| - interval=15) |
| 91 | + |
| 92 | + |
| 93 | +@needs_pandas_0_22 |
| 94 | +@pytest.mark.flaky(reruns=5, reruns_delay=2) |
| 95 | +def test_get_psm3_check_leap_day(nrel_api_key): |
| 96 | + _, data_2012 = psm3.get_psm3(LATITUDE, LONGITUDE, nrel_api_key, |
| 97 | + PVLIB_EMAIL, names="2012", interval=60, |
| 98 | + leap_day=True) |
| 99 | + assert len(data_2012) == (8760 + 24) |
| 100 | + |
| 101 | + |
| 102 | +@pytest.mark.parametrize('latitude, longitude, api_key, names, interval', |
| 103 | + [(LATITUDE, LONGITUDE, 'BAD', 'tmy-2017', 60), |
| 104 | + (51, -5, nrel_api_key, 'tmy-2017', 60), |
| 105 | + (LATITUDE, LONGITUDE, nrel_api_key, 'bad', 60), |
| 106 | + (LATITUDE, LONGITUDE, nrel_api_key, '2017', 15), |
| 107 | + ]) |
| 108 | +@needs_pandas_0_22 |
| 109 | +@pytest.mark.flaky(reruns=5, reruns_delay=2) |
| 110 | +def test_get_psm3_tmy_errors( |
| 111 | + latitude, longitude, api_key, names, interval |
| 112 | +): |
| 113 | + """Test get_psm3() for multiple erroneous input scenarios. |
| 114 | +
|
| 115 | + These scenarios include: |
| 116 | + * Bad API key -> HTTP 403 forbidden because api_key is rejected |
| 117 | + * Bad latitude/longitude -> Coordinates were not found in the NSRDB. |
| 118 | + * Bad name -> Name is not one of the available options. |
| 119 | + * Bad interval, single year -> Intervals can only be 30 or 60 minutes. |
| 120 | + """ |
| 121 | + with pytest.raises(HTTPError) as excinfo: |
| 122 | + psm3.get_psm3(latitude, longitude, api_key, PVLIB_EMAIL, |
| 123 | + names=names, interval=interval) |
| 124 | + # ensure the HTTPError caught isn't due to overuse of the API key |
| 125 | + assert "OVER_RATE_LIMIT" not in str(excinfo.value) |
94 | 126 |
|
95 | 127 |
|
96 | 128 | @pytest.fixture
|
|
0 commit comments