Repository: sunpy/sunpy

Issue:
Test failure due to 360 degrees not being recognized as having the same meaning as zero degrees.
<!-- This comments are hidden when you submit the issue so you do not need to remove them!
Please be sure to check out our contributing guidelines: https://github.com/sunpy/sunpy/blob/master/CONTRIBUTING.rst
Please be sure to check out our code of conduct:
https://github.com/sunpy/sunpy/blob/master/CODE_OF_CONDUCT.rst -->

<!-- Please have a search on our GitHub repository to see if a similar issue has already been posted.
If a similar issue is closed, have a quick look to see if you are satisfied by the resolution.
If not please go ahead and open an issue! -->

### Description
<!-- Provide a general description of the bug. -->
A bug showed up in the CI for #2916.

________________________________ test_hcrs_hgs _________________________________
```
    def test_hcrs_hgs():
        # Get the current Earth location in HCRS
        now = Time(parse_time('now'))
        earth_hcrs = SkyCoord(get_body_barycentric('earth', now), frame='icrs', obstime=now).hcrs
    
        # Convert from HCRS to HGS
        earth_hgs = earth_hcrs.transform_to(HeliographicStonyhurst)
    
        # The HGS longitude of the Earth should be zero within numerical error
>       assert quantity_allclose(earth_hgs.lon, 0*u.deg, atol=1e-12*u.deg)
E       assert False
E        +  where False = quantity_allclose(<Longitude 360. deg>, (0 * Unit("deg")), atol=(1e-12 * Unit("deg")))
E        +    where <Longitude 360. deg> = <SkyCoord (HeliographicStonyhurst: obstime=2019-01-31 15:27:09.378755): (lon, lat, radius) in (deg, deg, AU)\n    (360., -5.9683332, 0.98522121)>.lon
E        +    and   Unit("deg") = u.deg
E        +    and   Unit("deg") = u.deg

sunpy/coordinates/tests/test_transformations.py:99: AssertionError
```


### Expected behavior
<!-- What did you expect to happen. -->

360 degrees is also zero degrees.  Probably this test should not have failed

### Actual behavior
<!-- What actually happened. -->
<!-- Was the output confusing or poorly described? -->
It did fail!

### Steps to Reproduce
<!-- Ideally a code example could be provided so we can run it ourselves. -->
<!-- If you are pasting code, use tripe backticks (```) around your code snippet. -->

### System Details
<!-- We at least need to know the SunPy version you are using. -->
<!-- We provide a short function in SunPy that will provide some of the below information. -->
<!-- It is sunpy.util.system_info(), this is optional but strongly recommended. -->
==========================================================
 SunPy Installation Information

==========================================================

###########
 General
###########
Time : Thursday, 31. January 2019 04:02PM UT
System : Darwin
Processor : i386
Arch : 64bit
SunPy : 0.9.2
SunPy_git : eded238635695f1c28a8b8e29bf1aa7de0bcee05
OS: Mac OS X 10.13.6 (i386)


###########
 Required Libraries 
###########
Python: 3.6.8
NumPy: 1.15.4
SciPy: 1.1.0
matplotlib: 3.0.2
Astropy: 3.1.1
Pandas: 0.24.0


###########
 Recommended Libraries 
###########
beautifulsoup: 4.7.1
PyQt: NOT INSTALLED
SUDS: 0.6
Sqlalchemy: 1.2.16
Requests: 2.21.0



Discussion:

Resolving patch:
diff --git a/sunpy/instr/lyra.py b/sunpy/instr/lyra.py
--- a/sunpy/instr/lyra.py
+++ b/sunpy/instr/lyra.py
@@ -415,7 +415,7 @@ def get_lytaf_events(start_time, end_time, lytaf_path=None,
     --------
     Get all events in the LYTAF files for January 2014
         >>> from sunpy.instr.lyra import get_lytaf_events
-        >>> lytaf = get_lytaf_events('2014-01-01', '2014-02-01')  # doctest: +REMOTE_DATA
+        >>> lytaf = get_lytaf_events('2014-01-01', '2014-02-01')  # doctest: +SKIP
 
     """
     # Check inputs


Test patch:
diff --git a/sunpy/coordinates/tests/test_transformations.py b/sunpy/coordinates/tests/test_transformations.py
--- a/sunpy/coordinates/tests/test_transformations.py
+++ b/sunpy/coordinates/tests/test_transformations.py
@@ -96,7 +96,7 @@ def test_hcrs_hgs():
     earth_hgs = earth_hcrs.transform_to(HeliographicStonyhurst)
 
     # The HGS longitude of the Earth should be zero within numerical error
-    assert quantity_allclose(earth_hgs.lon, 0*u.deg, atol=1e-12*u.deg)
+    assert quantity_allclose(earth_hgs.lon % (360*u.deg), 0*u.deg, atol=1e-12*u.deg)
 
     # The HGS latitude and radius should be within valid ranges
     assert quantity_allclose(earth_hgs.lat, 0*u.deg, atol=7.3*u.deg)
diff --git a/sunpy/database/tests/test_attrs.py b/sunpy/database/tests/test_attrs.py
--- a/sunpy/database/tests/test_attrs.py
+++ b/sunpy/database/tests/test_attrs.py
@@ -402,28 +402,43 @@ def test_walker_create_fitsheader_inverted(session):
             id=9, path='/tmp', download_time=datetime(2005, 6, 15, 9))]
 
 
-@pytest.mark.flaky(reruns=5)
 @pytest.mark.remote_data
 def test_walker_create_vso_instrument(vso_session):
     entries = walker.create(vso.attrs.Instrument('RHESSI'), vso_session)
+    # TODO: Flaky
     expected = [
         tables.DatabaseEntry(id=1, source=u'RHESSI', provider=u'LSSP',
-            physobs=u'intensity',
-            fileid=u'/hessidata/2011/09/20/hsi_20110920_010920',
-            observation_time_start=datetime(2011, 9, 20, 1, 9, 20),
-            observation_time_end=datetime(2011, 9, 20, 2, 27, 40),
-            instrument=u'RHESSI', wavemin=0.4132806579880238,
-            wavemax=7.293188082141598e-05),
+                             physobs=u'intensity',
+                             fileid=u'/hessidata/2011/09/20/hsi_20110920_010920',
+                             observation_time_start=datetime(2011, 9, 20, 1, 9, 20),
+                             observation_time_end=datetime(2011, 9, 20, 2, 27, 40),
+                             instrument=u'RHESSI', wavemin=0.4132806579880238,
+                             wavemax=7.293188082141598e-05),
         tables.DatabaseEntry(id=2, source=u'RHESSI', provider=u'LSSP',
-            physobs=u'intensity',
-            fileid=u'/hessidata/2011/09/19/hsi_20110919_233340',
-            observation_time_start=datetime(2011, 9, 19, 23, 33, 40),
-            observation_time_end=datetime(2011, 9, 20, 1, 9, 20),
-            instrument=u'RHESSI', wavemin=0.4132806579880238,
-            wavemax=7.293188082141598e-05)]
-
+                             physobs=u'intensity',
+                             fileid=u'/hessidata/2011/09/19/hsi_20110919_233340',
+                             observation_time_start=datetime(2011, 9, 19, 23, 33, 40),
+                             observation_time_end=datetime(2011, 9, 20, 1, 9, 20),
+                             instrument=u'RHESSI', wavemin=0.4132806579880238,
+                             wavemax=7.293188082141598e-05)]
+    expected_2 = [
+        tables.DatabaseEntry(id=1, source=u'RHESSI', provider=u'LSSP',
+                             physobs=u'intensity',
+                             fileid=u'/hessidata/2011/09/19/hsi_20110919_233340',
+                             observation_time_start=datetime(2011, 9, 19, 23, 33, 40),
+                             observation_time_end=datetime(2011, 9, 20, 1, 9, 20),
+                             instrument=u'RHESSI', wavemin=0.4132806579880238,
+                             wavemax=7.293188082141598e-05),
+        tables.DatabaseEntry(id=2, source=u'RHESSI', provider=u'LSSP',
+                             physobs=u'intensity',
+                             fileid=u'/hessidata/2011/09/20/hsi_20110920_010920',
+                             observation_time_start=datetime(2011, 9, 20, 1, 9, 20),
+                             observation_time_end=datetime(2011, 9, 20, 2, 27, 40),
+                             instrument=u'RHESSI', wavemin=0.4132806579880238,
+                             wavemax=7.293188082141598e-05)]
     assert len(entries) == len(expected)
-    assert entries == expected
+    assert entries in [expected, expected_2]
+
 
 @pytest.mark.remote_data
 def test_walker_create_wave(vso_session):
@@ -433,18 +448,25 @@ def test_walker_create_wave(vso_session):
     assert len(entries) == 0
 
 
-@pytest.mark.flaky(reruns=5)
 @pytest.mark.remote_data
 def test_walker_create_time(vso_session):
     time = vso.attrs.Time(
         datetime(2011, 9, 17, 0, 0, 0), datetime(2011, 9, 20, 0, 0, 0))
     entries = walker.create(time, vso_session)
     assert len(entries) == 1
-    assert entries == [
-        tables.DatabaseEntry(id=2, source=u'RHESSI', provider=u'LSSP',
-            physobs=u'intensity',
-            fileid=u'/hessidata/2011/09/19/hsi_20110919_233340',
-            observation_time_start=datetime(2011, 9, 19, 23, 33, 40),
-            observation_time_end=datetime(2011, 9, 20, 1, 9, 20),
-            instrument=u'RHESSI', wavemin=0.4132806579880238,
-            wavemax=7.293188082141598e-05)]
+    # TODO: Flaky and the only change the id number.
+    assert entries in [
+        [tables.DatabaseEntry(id=1, source=u'RHESSI', provider=u'LSSP',
+                              physobs=u'intensity',
+                              fileid=u'/hessidata/2011/09/19/hsi_20110919_233340',
+                              observation_time_start=datetime(2011, 9, 19, 23, 33, 40),
+                              observation_time_end=datetime(2011, 9, 20, 1, 9, 20),
+                              instrument=u'RHESSI', wavemin=0.4132806579880238,
+                              wavemax=7.293188082141598e-05)],
+        [tables.DatabaseEntry(id=2, source=u'RHESSI', provider=u'LSSP',
+                              physobs=u'intensity',
+                              fileid=u'/hessidata/2011/09/19/hsi_20110919_233340',
+                              observation_time_start=datetime(2011, 9, 19, 23, 33, 40),
+                              observation_time_end=datetime(2011, 9, 20, 1, 9, 20),
+                              instrument=u'RHESSI', wavemin=0.4132806579880238,
+                              wavemax=7.293188082141598e-05)]]
diff --git a/sunpy/database/tests/test_tables.py b/sunpy/database/tests/test_tables.py
--- a/sunpy/database/tests/test_tables.py
+++ b/sunpy/database/tests/test_tables.py
@@ -110,7 +110,6 @@ def test_tag_hashability():
     assert isinstance(Tag(''), Hashable)
 
 
-@pytest.mark.flaky(reruns=5)
 @pytest.mark.remote_data
 def test_entries_from_fido_search_result(fido_search_result):
     entries = list(entries_from_fido_search_result(fido_search_result))
@@ -238,15 +237,17 @@ def test_entry_from_qr_block_with_missing_physobs(qr_block_with_missing_physobs)
     assert entry == expected_entry
 
 
-@pytest.mark.flaky(reruns=5)
 @pytest.mark.remote_data
 def test_entry_from_qr_block_kev(qr_block_with_kev_unit):
     # See issue #766.
     entry = DatabaseEntry._from_query_result_block(qr_block_with_kev_unit)
     assert entry.source == 'RHESSI'
     assert entry.provider == 'LSSP'
-    assert entry.fileid == '/hessidata/2011/09/20/hsi_20110920_010920'
-    assert entry.observation_time_start == datetime(2011, 9, 20, 1, 9, 20)
+    # TODO: Flaky test that needs a fix
+    assert entry.fileid in ['/hessidata/2011/09/19/hsi_20110919_233340',
+                            '/hessidata/2011/09/20/hsi_20110920_010920']
+    assert entry.observation_time_start in [datetime(2011, 9, 20, 1, 9, 20),
+                                            datetime(2011, 9, 19, 23, 33, 40)]
     assert entry.observation_time_end == datetime(2011, 9, 20, 2, 27, 40)
     assert entry.instrument == 'RHESSI'
     assert round(entry.wavemin, 3) == 0.413
diff --git a/sunpy/net/dataretriever/tests/test_eve.py b/sunpy/net/dataretriever/tests/test_eve.py
--- a/sunpy/net/dataretriever/tests/test_eve.py
+++ b/sunpy/net/dataretriever/tests/test_eve.py
@@ -1,8 +1,4 @@
-import datetime
-
 import pytest
-from hypothesis import given, settings, HealthCheck
-from sunpy.net.tests.strategies import time_attr, Times
 
 from sunpy.time import parse_time
 from sunpy.time.timerange import TimeRange
@@ -85,11 +81,9 @@ def test_fido(query):
 
 
 @pytest.mark.remote_data
-@given(time_attr(time=Times(
-    max_value=datetime.datetime(datetime.datetime.utcnow().year, 1, 1, 0, 0),
-    min_value=datetime.datetime(2010, 1, 1, 0, 0),
-)))
-@settings(max_examples=2, deadline=None, suppress_health_check=[HealthCheck.hung_test])
+@pytest.mark.parametrize(
+    'time',
+    [(a.Time('2012/10/4', '2012/10/6')), (a.Time('2012/11/27', '2012/11/27'))])
 def test_levels(time):
     """
     Test the correct handling of level 0 / 1.
diff --git a/sunpy/net/dataretriever/tests/test_goes_ud.py b/sunpy/net/dataretriever/tests/test_goes_ud.py
--- a/sunpy/net/dataretriever/tests/test_goes_ud.py
+++ b/sunpy/net/dataretriever/tests/test_goes_ud.py
@@ -1,5 +1,5 @@
 import pytest
-from hypothesis import given, example, settings, HealthCheck
+from hypothesis import given, example, settings
 
 from astropy.time import TimeDelta
 import astropy.units as u
@@ -65,7 +65,7 @@ def test_fixed_satellite(LCClient):
         assert "go13" in resp.url
 
 
-@settings(deadline=None, suppress_health_check=[HealthCheck.hung_test])
+@settings(deadline=50000)
 @example(a.Time("2006-08-01", "2006-08-01"))
 # This example tests a time range with a satellite jump and no overlap
 @example(a.Time("2009-11-30", "2009-12-3"))
@@ -121,6 +121,7 @@ def test_fido(time, instrument):
     assert len(response) == qr._numfile
 
 
+@pytest.mark.flaky(reruns=5)
 @given(goes_time())
 def test_time_for_url(LCClient, time):
     time = time.start.strftime("%Y/%m/%d")
diff --git a/sunpy/net/dataretriever/tests/test_lyra_ud.py b/sunpy/net/dataretriever/tests/test_lyra_ud.py
--- a/sunpy/net/dataretriever/tests/test_lyra_ud.py
+++ b/sunpy/net/dataretriever/tests/test_lyra_ud.py
@@ -2,14 +2,14 @@
 
 from sunpy.time.timerange import TimeRange
 from sunpy.time import parse_time
-from sunpy.net.vso.attrs import Time, Instrument, Source
+from sunpy.net.vso.attrs import Time, Instrument
 from sunpy.net.dataretriever.client import QueryResponse
 import sunpy.net.dataretriever.sources.lyra as lyra
 from sunpy.net.fido_factory import UnifiedResponse
 from sunpy.net import Fido
 from sunpy.net import attrs as a
 
-from hypothesis import given, settings, HealthCheck
+from hypothesis import given, settings
 from sunpy.net.tests.strategies import time_attr
 
 LCClient = lyra.LYRAClient()
@@ -50,7 +50,7 @@ def test_can_handle_query(time):
     assert ans2 is False
 
 
-@settings(deadline=None, suppress_health_check=[HealthCheck.hung_test])
+@settings(deadline=50000)
 @given(time_attr())
 def test_query(time):
     qr1 = LCClient.search(time, Instrument('lyra'))
diff --git a/sunpy/net/dataretriever/tests/test_noaa.py b/sunpy/net/dataretriever/tests/test_noaa.py
--- a/sunpy/net/dataretriever/tests/test_noaa.py
+++ b/sunpy/net/dataretriever/tests/test_noaa.py
@@ -14,7 +14,6 @@
 LCClient = noaa.NOAAIndicesClient()
 
 
-
 def mock_query_object(start_date, end_date):
     """
     Creation of a QueryResponse object, and prefill some
diff --git a/sunpy/net/dataretriever/tests/test_norh.py b/sunpy/net/dataretriever/tests/test_norh.py
--- a/sunpy/net/dataretriever/tests/test_norh.py
+++ b/sunpy/net/dataretriever/tests/test_norh.py
@@ -11,7 +11,7 @@
 from sunpy.net import Fido
 from sunpy.net import attrs as a
 
-from hypothesis import given, settings, HealthCheck
+from hypothesis import given, settings
 
 from sunpy.net.tests.strategies import time_attr, range_time
 
@@ -48,11 +48,10 @@ def test_can_handle_query(time):
     ans2 = norh.NoRHClient._can_handle_query(time)
     assert ans2 is False
 
-
-@settings(deadline=None,  suppress_health_check=[HealthCheck.hung_test])
 @pytest.mark.remote_data
 @pytest.mark.parametrize("wave", [a.Wavelength(17*u.GHz), a.Wavelength(34*u.GHz)])
 @given(time=range_time(Time('1992-6-1')))
+@settings(max_examples=2, deadline=50000)
 def test_query(time, wave):
     qr1 = norh.NoRHClient().search(time, a.Instrument('norh'), wave)
     assert isinstance(qr1, QueryResponse)
diff --git a/sunpy/net/jsoc/tests/test_jsoc.py b/sunpy/net/jsoc/tests/test_jsoc.py
--- a/sunpy/net/jsoc/tests/test_jsoc.py
+++ b/sunpy/net/jsoc/tests/test_jsoc.py
@@ -50,7 +50,6 @@ def test_query():
     assert len(Jresp) == 2
 
 
-@pytest.mark.flaky(reruns=5)
 @pytest.mark.remote_data
 def test_post_pass():
     responses = client.search(
diff --git a/sunpy/net/tests/strategies.py b/sunpy/net/tests/strategies.py
--- a/sunpy/net/tests/strategies.py
+++ b/sunpy/net/tests/strategies.py
@@ -8,7 +8,6 @@
 from hypothesis.strategies import one_of, datetimes, sampled_from
 
 import astropy.time
-import astropy.units as u
 from astropy.time import Time
 
 from sunpy.net import attrs as a
@@ -32,15 +31,16 @@ def Times(draw, max_value, min_value):
 def TimeDelta(draw):
     """
     Timedelta strategy that limits the maximum timedelta to being positive and
-    abs max is about 100 weeks + 100 days + 100 hours + a bit
+    abs max is about 10 weeks + 10 days + 10 hours + 10 minutes + a bit
     """
-    keys = st.sampled_from(['days', 'seconds', 'microseconds', 'milliseconds',
-                            'minutes', 'hours', 'weeks'])
-    values = st.floats(min_value=1, max_value=100)
+    keys = st.sampled_from(['weeks', 'days', 'hours', 'minutes', 'seconds'])
+    values = st.floats(min_value=1, max_value=10)
     delta = datetime.timedelta(**draw(st.dictionaries(keys, values)))
-    # We don't want a 0 timedelta
     delta = astropy.time.TimeDelta(delta, format='datetime')
+
+    # We don't want a 0 timedelta
     assume(delta.sec > 0)
+
     return delta
 
 
@@ -68,17 +68,15 @@ def online_instruments():
 
 @st.composite
 def time_attr(draw, time=Times(
-    max_value=datetime.datetime(datetime.datetime.utcnow().year, 1, 1, 0, 0),
-    min_value=datetime.datetime(1900, 1, 1, 0, 0)
-    ),
+              max_value=datetime.datetime(datetime.datetime.utcnow().year, 1, 1, 0, 0),
+              min_value=datetime.datetime(1981, 1, 1, 0, 0)),
               delta=TimeDelta()):
     """
-    Create an a.Time where it's always positive and doesn't have a massive time
-    delta.
+    Create an a.Time where it's always positive.
     """
     t1 = draw(time)
     t2 = t1 + draw(delta)
-    # We can't download data from the future...
+    # We can't download data from the future.
     assume(t2 < Time.now())
 
     return a.Time(t1, t2)
@@ -86,37 +84,37 @@ def time_attr(draw, time=Times(
 
 @st.composite
 def goes_time(draw, time=Times(
-    max_value=datetime.datetime(datetime.datetime.utcnow().year, 1, 1, 0, 0),
-    min_value=datetime.datetime(1981, 1, 1, 0, 0)),
+              max_value=datetime.datetime(datetime.datetime.utcnow().year, 1, 1, 0, 0),
+              min_value=datetime.datetime(1981, 1, 1, 0, 0)),
               delta=TimeDelta()):
     """
-    Create an a.Time where it's always positive and doesn't have a massive time
-    delta.
+    Create an a.Time where it's always positive.
     """
     t1 = draw(time)
-    t2 = t1 + draw(delta)
+    delta = draw(delta)
+    t2 = t1 + delta
     # We can't download data from the future.
     assume(t2 < Time.now())
 
-    tr = TimeRange(t1, t2)
     # There is no GOES data for this date.
     # We seem to pick up an extra micro or millisecond when we create t1
     # This seems to be test dependant.
     # `test_fido_indexing` adds 1 millisecond.
     # `test_offline_fido` adds 1 microsecond.
     # TODO: Track this issue down.
-    # To avoid this we change the start of the timerange
-    tr._t1 -= 1*u.s
-    assume(Time('1983-05-01') not in tr)
-    assume(Time('1983-05-01') + draw(delta) not in tr)
+    assume(not (t1 <= Time('1983-05-01') <= t2))
+    assume(not (t1 <= (Time('1983-05-01') + delta) <= t2))
+
+    tr = TimeRange(t1, t2)
 
     return a.Time(tr)
 
 
 def range_time(min_date, max_date=Time.now()):
     time = Times(
-        min_value=datetime.datetime(1960, 1, 1, 0, 0),
-        max_value=datetime.datetime(datetime.MAXYEAR, 1, 1, 0, 0),
+        min_value=datetime.datetime(1981, 1, 1, 0, 0),
+        max_value=datetime.datetime(datetime.datetime.utcnow().year, 1, 1, 0, 0),
     )
     time = time.filter(lambda x: min_date < x < max_date)
+
     return time_attr(time=time)
diff --git a/sunpy/net/tests/test_fido.py b/sunpy/net/tests/test_fido.py
--- a/sunpy/net/tests/test_fido.py
+++ b/sunpy/net/tests/test_fido.py
@@ -5,7 +5,7 @@
 
 import pytest
 import hypothesis.strategies as st
-from hypothesis import given, assume, example, settings, HealthCheck
+from hypothesis import given, assume, example, settings
 
 import astropy.units as u
 from drms import DrmsQueryError
@@ -57,15 +57,16 @@ def online_query(draw, instrument=online_instruments(), time=time_attr()):
     return query
 
 
-@settings(deadline=None, suppress_health_check=[HealthCheck.hung_test])
+@settings(deadline=50000)
 @given(offline_query())
 def test_offline_fido(query):
     unifiedresp = Fido.search(query)
     check_response(query, unifiedresp)
 
 
-@settings(deadline=None,  suppress_health_check=[HealthCheck.hung_test])
+@settings(deadline=50000)
 @pytest.mark.remote_data
+@pytest.mark.flaky(reruns=5)
 @given(online_query())
 def test_online_fido(query):
     unifiedresp = Fido.search(query)
@@ -247,7 +248,7 @@ def filter_queries(queries):
     return attr.and_(queries) not in queries
 
 
-@settings(deadline=None, suppress_health_check=[HealthCheck.hung_test])
+@settings(deadline=50000)
 @given(st.tuples(offline_query(), offline_query()).filter(filter_queries))
 def test_fido_indexing(queries):
     query1, query2 = queries
@@ -286,7 +287,7 @@ def test_fido_indexing(queries):
         res[1.0132]
 
 
-@settings(deadline=None, suppress_health_check=[HealthCheck.hung_test])
+@settings(deadline=50000)
 @given(st.tuples(offline_query(), offline_query()).filter(filter_queries))
 def test_fido_iter(queries):
     query1, query2 = queries
@@ -301,7 +302,7 @@ def test_fido_iter(queries):
         assert isinstance(resp, QueryResponse)
 
 
-@settings(deadline=None, suppress_health_check=[HealthCheck.hung_test])
+@settings(deadline=50000)
 @given(offline_query())
 def test_repr(query):
     res = Fido.search(query)