text: import os
  import sys
  
  import ee
  import requests
  
  from sql2gee import SQL2GEE
  from sql2gee.utils.jsonSql import JsonSql
  
  # Quick hack, if using a local mac, assume you can initilise using the below...
  if sys.platform == 'darwin':
      ee.Initialize()
  else:
      EE_ACCOUNT = os.environ['EE_ACCOUNT']
      EE_PRIVATE_KEY_FILE = 'privatekey.json'
  
      gee_credentials = ee.ServiceAccountCredentials(EE_ACCOUNT, EE_PRIVATE_KEY_FILE)
      ee.Initialize(gee_credentials)
  
  
  def test_metadata():
      sql = "SELECT ST_HISTOGRAM(rast, elevation, 10, true) FROM CGIAR/SRTM90_V4"
      q = SQL2GEE(JsonSql(sql).to_json())
      assert q.metadata['type'] == 'IMAGE'
      assert q.metadata['name'] == 'projects/earthengine-public/assets/CGIAR/SRTM90_V4'
      assert q.metadata['id'] == 'CGIAR/SRTM90_V4'
      assert q.metadata['title'] == 'SRTM Digital Elevation Data Version 4'
      assert 'properties' in q.metadata
      assert 'description' in q.metadata
      assert 'bands' in q.metadata
      return
  
  
  def test_type():
      sql = "SELECT ST_HISTOGRAM(rast, elevation, 10, true) FROM CGIAR/SRTM90_V4"
      q = SQL2GEE(JsonSql(sql).to_json())
      assert q.type == 'IMAGE'
      return
  
  
  def test_retrieve_st_metadata():
      """Test that basic raster metadata (in dictionary format) is returned when
      the postgis ST_METADATA() command is given.
      Notes:
          CGIAR/SRTM90_V4 is a 90m Elevation image.
      """
      sql = "SELECT ST_METADATA(rast) FROM CGIAR/SRTM90_V4"
      q = SQL2GEE(JsonSql(sql).to_json())
  
      result = q.response()[0]['st_metadata']
  
      assert result['type'] == 'IMAGE'
      assert result['name'] == 'projects/earthengine-public/assets/CGIAR/SRTM90_V4'
      assert result['id'] == 'CGIAR/SRTM90_V4'
      assert result['title'] == 'SRTM Digital Elevation Data Version 4'
      assert 'properties' in result
      assert 'description' in result
      assert 'bands' in result
  
      return
  
  
  def test_retrieve_st_band_metadata():
      """Test that basic raster metadata (in dictionary format) is returned when
      the postgis ST_BANDMETADATA() command is given.
      Notes:
          CGIAR/SRTM90_V4 is a 90m Elevation image.
      """
      sql = "SELECT ST_BANDMETADATA(rast, elevation) FROM CGIAR/SRTM90_V4"
      q = SQL2GEE(JsonSql(sql).to_json())
  
      result = q.response()[0]['st_bandmetadata']
  
      assert result['id'] == 'elevation'
      assert result['dataType'] == {'precision': 'INT', 'range': {'min': -32768, 'max': 32767}}
      assert result['grid'] == {'crsCode': 'EPSG:4326', 'dimensions': {'width': 432000, 'height': 144000},
                                'affineTransform': {'scaleX': 0.000833333333333, 'translateX': -180,
                                                    'scaleY': -0.000833333333333, 'translateY': 60}}
      assert result['pyramidingPolicy'] == 'MEAN'
      return
  
  
  def test_ST_HISTOGRAM():
      """Test that a dictionary containing a list of expected length and values is returned"""
      sql = "SELECT ST_HISTOGRAM(rast, 1, auto, true) FROM CGIAR/SRTM90_V4"
      q = SQL2GEE(JsonSql(sql).to_json())
      response = q.response()[0]['st_histogram']
      assert response['elevation'][0] == [-32.0, 5.149019607843137], 'First bin incorrect'
      assert response['elevation'][-1] == [1088.0, 1.0], 'Last bin incorrect'
      return
  
  
  def test_ST_HISTORGRAM_multiband_image():
      """ST_HISTOGRAM should give back a dic with the first band, and best-guess binning if auto argument is specified"""
      expected_keys = ['st_histogram']
      sql = "SELECT ST_HISTOGRAM(rast, 1, auto, true) FROM 'CGIAR/SRTM90_V4'"
      q = SQL2GEE(JsonSql(sql).to_json())
      response = q.response()
      assert isinstance(response, list), "Dictionary was not returned as a response"
      assert len(response) == 1, "Size of the dictionary was diffrent from expected response"
      assert list(response[0].keys()) == expected_keys, "Expected keys in response dictionary were not returned"
      for key in response[0][expected_keys[0]].keys():
          if response[0][expected_keys[0]][key] != None:
              assert len(response[0][expected_keys[0]][key]) == 36, "Expected 210 bins in histogram"
      return
  
  
  def test_ST_HISTORGRAM_keywords_select_specific_band_and_bins():
      """Without any specific keywords set, ST_HISTOGRAM gives back a dic with the first band, and best-guess binning"""
      expected_keys = ['st_histogram']
      sql = "SELECT ST_HISTOGRAM(raster, 'elevation', 10, true) FROM 'CGIAR/SRTM90_V4'"
      q = SQL2GEE(JsonSql(sql).to_json())
      response = q.response()
  
      assert isinstance(response, list), "Dictionary was not returned as a response"
      assert len(response) == 1, "Size of the dictionary was diffrrent from expected response"
  
      assert list(response[0].keys()) == expected_keys, "Expected elevation in response dictionary"
      for key in response[0][expected_keys[0]].keys():
          if response[0][expected_keys[0]][key] != None:
              assert len(response[0][expected_keys[0]][key]) == 10, "Expected 10 bins in histogram"
      return
  
  
  def test_ST_HISTORGRAM_keywords_reversed():
      """Without any specific keywords set, ST_HISTOGRAM gives back a dic with the first band, and best-guess binning"""
      sql = "SELECT ST_HISTOGRAM(raster, 'elevation', 10, false) FROM 'CGIAR/SRTM90_V4'"
      q = SQL2GEE(JsonSql(sql).to_json())
      response = q.response()
      assert response[0]['st_histogram']['elevation'][0][0] > response[0]['st_histogram']['elevation'][-1][
          0], "Bins should be in reverse order"
      return
  
  
  def test_ST_SUMMARYSTATS():
      """Check an expected dictionary is returned via the ST_SUMMARYSTATS() keyword"""
      expected = [{u'st_summarystats': {u'elevation': {'count': 2747198,
                                                       'max': 7159,
                                                       'mean': 689.8474833769903,
                                                       'min': -415,
                                                       'stdev': 865.9582784994756,
                                                       'sum': 1859471136.0274282}}}]
      sql = "SELECT ST_SUMMARYSTATS() FROM 'CGIAR/SRTM90_V4'"
      q = SQL2GEE(JsonSql(sql).to_json())
      q.response() == expected, "Summary stats did not match expected result"
      return
  
  
  def test_ST_SUMMARYSTATS_with_area_restriction_from_geojson_polygon():
      """First, I need to construct a simple polygon out of multipolygon data, and pass that to SQL2GEE"""
      expected = [{u'st_summarystats': {
          u'elevation': {'count': 4, 'min': 1041, 'max': 1051, 'sum': 505.6705882352941, 'stdev': 4.272001872658765,
                         'mean': 1048.341463414634}}}]
      gstore = "https://api.resourcewatch.org/v1/geostore/ca38fa80a4ffa9ac6217a7e0bf71e6df"
      r = requests.get(gstore).json().get('data').get('attributes').get('geojson')
  
      # Initilise an SQL2GEE query object with geojson
      sql = "SELECT ST_SUMMARYSTATS() FROM CGIAR/SRTM90_V4"
      q = SQL2GEE(JsonSql(sql).to_json(), geojson=r)
      response = q.response()
      assert response == expected, "Response was not equal to expected values"
      return
  
  
  def test_ST_SUMMARYSTATS_with_area_restriction_via_passing_geojson_multipolygon():
      """If a geojson argument is passed to SQL2GEE it should be converted into an Earth Engine Feature Collection.
      This should then be used to subset the area considered for results."""
      # Get a test geojson object by accessing Vizzuality's geostore
      expected = [{u'st_summarystats': {
          u'elevation': {'count': 4, 'min': 1041, 'max': 1051, 'sum': 505.6705882352941, 'stdev': 4.272001872658765,
                         'mean': 1048.341463414634}}}]
      gstore = "https://api.resourcewatch.org/v1/geostore/ca38fa80a4ffa9ac6217a7e0bf71e6df"
      r = requests.get(gstore).json().get('data').get('attributes').get('geojson')
      # Initialise an SQL2GEE query object with geojson
      sql = "SELECT ST_SUMMARYSTATS() FROM CGIAR/SRTM90_V4"
      q = SQL2GEE(JsonSql(sql).to_json(), geojson=r)
      response = q.response()
      assert response == expected, "Area restricted response did not match expected result"
      return
  
  
  def test_ST_SUMMARYSTATS_with_tricky_data():
      """A problem with image data that is a composite. We will try and get a response, if an EEException is raised,
      a default (near-global) feature collection will be passed to the area, which will cause reducers to correctly
      treat it like an image."""
      sql = 'SELECT ST_SUMMARYSTATS() FROM "USGS/GFSAD1000_V1"'
      q = SQL2GEE(JsonSql(sql).to_json())
      assert isinstance(q.response(), list), "Dictionary should have been returned"
      return
  
  
  def test_ST_HISTOGRAM_bins_correct():
      """Hansen Forest change dataset has a band called lossyear, which has integer values of 0->14.
      Make a test to create a bin for each integer."""
      sql = 'SELECT ST_HISTOGRAM(raster, lossyear, 15, true) FROM "UMD/hansen/global_forest_change_2019_v1_7"'
      q = SQL2GEE(JsonSql(sql).to_json())
      response = q.response()
      assert len(response[0]['st_histogram']['lossyear']) == 15, "15 bins expected"
      assert response[0]['st_histogram']['lossyear'][14][0] == 18.733333333333334
      return
  
  
  def test_ST_GeomFromGeoJSON():
      """Test that SQL queries can set a geojson object that gets correctly used."""
      sql = """SELECT ST_SUMMARYSTATS() as x FROM 'CGIAR/SRTM90_V4'
                   WHERE ST_INTERSECTS(ST_SetSRID(ST_GeomFromGeoJSON('{\"type\":\"Polygon\",
                   \"coordinates\":[[[-43.39599609375,-4.740675384778361],
                   [-43.39599609375,-4.959615024698014],
                   [-43.17626953125,-4.806364708499984],
                   [-43.39599609375,-4.740675384778361]]]}'),4326), the_geom)"""
  
      correct = {'x': {'elevation': {'count': 35205,
                                     'max': 172,
                                     'mean': 100.04437654442182,
                                     'min': 52,
                                     'stdev': 21.970242559380736,
                                     'sum': 3465299.4509803928}}}
  
      jsonQuery = JsonSql(sql).to_json()
      q = SQL2GEE(jsonQuery)
      response = q.response()[0]
  
      assert round(response['x']['elevation']['max'], 2) == round(correct['x']['elevation']['max'],
                                                                  2), "Incorrect response returned"
      assert round(response['x']['elevation']['count'], 2) == round(correct['x']['elevation']['count'],
                                                                    2), "Incorrect response returned"
      assert round(response['x']['elevation']['min'], 2) == round(correct['x']['elevation']['min'],
                                                                  2), "Incorrect response returned"
      assert round(response['x']['elevation']['mean'], 2) == round(correct['x']['elevation']['mean'],
                                                                   2), "Incorrect response returned"
      assert round(response['x']['elevation']['sum'], 2) == round(correct['x']['elevation']['sum'],
                                                                  2), "Incorrect response returned"
      assert round(response['x']['elevation']['stdev'], 2) == round(correct['x']['elevation']['stdev'],
                                                                    2), "Incorrect response returned"
      return
  
  
  def test_auto_bug():
      """Test a bug that was noticed regarding the use of auto as an argument"""
      sql = "SELECT ST_HISTOGRAM(rast, 1, auto, true) FROM CGIAR/SRTM90_V4"
      q = SQL2GEE(JsonSql(sql).to_json())
      try:
          _ = q.response()
      except:
          # If the response failed to return fail this test...
          assert q.response() == None
      return
  
  
  def test_band_byname():
      """Test a bug that was noticed regarding the use of auto as an argument"""
      sql = "SELECT ST_HISTOGRAM(rast, 'elevation', auto, true) FROM CGIAR/SRTM90_V4"
      q = SQL2GEE(JsonSql(sql).to_json())
      try:
          _ = q.response()
      except:
          # If the response failed to return fail this test...
          assert q.response == None
      return
  
  
  def test_valuecount_categorical():
      """Test a bug that was noticed regarding the use of auto as an argument"""
      sql = "SELECT ST_valuecount(rast, 'seasonality', false) as t FROM 'JRC/GSW1_2/GlobalSurfaceWater'"
      correct = [{'t': {
          'seasonality': {'1': 269354, '10': 13929, '11': 2506, '12': 19746788, '2': 79053, '3': 18373, '4': 11953,
                          '5': 11982, '6': 3361, '7': 60005, '8': 17058, '9': 20501}}}]
      q = SQL2GEE(JsonSql(sql).to_json())
      assert q.response() == correct, "Incorrect response returned"
      return
  
  
  def test_valuecount_categorical_true():
      """Test a bug that was noticed regarding the use of auto as an argument"""
      sql = "SELECT ST_valuecount(rast, 'seasonality', true) FROM 'JRC/GSW1_2/GlobalSurfaceWater'"
      correct = [{'st_valuecount': {
          'seasonality': {'1': 257090.0, '10': 53411.0, '11': 3326.0, '12': 18471661.0, '2': 86180.0, '3': 17032.0,
                          '4': 40943.0, '5': 27166.0, '6': 4363.0, '7': 150599.0, '8': 30365.0, '9': 68880.0,
                          'null': 673491564.0}}}]
      q = SQL2GEE(JsonSql(sql).to_json())
      assert q.response() == correct, "Incorrect response returned"
      return
  
  
  def test_valuecount_categorical_true():
      """Test a bug that was noticed regarding the use of auto as an argument"""
      sql = "SELECT ST_valuecount(rast, 'seasonality', true) FROM 'JRC/GSW1_0/GlobalSurfaceWater'"
      correct = [{'st_valuecount': {
          'seasonality': {'1': 257090.0, '10': 53411.0, '11': 3326.0, '12': 18471661.0, '2': 86180.0, '3': 17032.0,
                          '4': 40943.0, '5': 27166.0, '6': 4363.0, '7': 150599.0, '8': 30365.0, '9': 68880.0,
                          'null': 673491564.0}}}]
      q = SQL2GEE(JsonSql(sql).to_json())
      response = q.response()
  
      assert response == correct, "Incorrect response returned"
      return
  