Как локально смоделировать файловую систему S3 для тестирования spark.read.csv с помощью pytest?

#pyspark #pytest #amazon-sagemaker #moto

Вопрос:

Что я пытаюсь сделать

Я пытаюсь выполнить модульное тестирование эквивалента следующей функции, используя pytest:

 def read_s3_csv_into_spark_df(s3_uri, spark):
    df = spark.read.csv(
        s3_uri.replace("s3://", "s3a://")
    )
    return df
 

Тест определяется следующим образом:

 def test_load_csv(self, test_spark_session, tmpdir):
    # here I 'upload' a fake csv file using tmpdir fixture and moto's mock_s3 decorator
    
    # now that the fake csv file is uploaded to s3, I try read into spark df using my function
    baseline_df = read_s3_csv_into_spark_df(
        s3_uri="s3a://bucket/key/baseline.csv",
        spark=test_spark_session
    )
 

В приведенном выше тесте используемый параметр test_spark_session определяется следующим образом:

 @pytest.fixture(scope="session")
def test_spark_session():
    test_spark_session = (
        SparkSession.builder.master("local[*]").appName("test").getOrCreate()
    )
    return test_spark_session
 

Проблема

Я работаю pytest на экземпляре ноутбука SageMaker, используя python 3.7, pytest 6.2.4 и pyspark 3.1.2. Я могу запускать другие тесты, создавая фрейм данных с использованием test_spark_session.createDataFrame , а затем выполняя агрегирование. Таким образом, локальный контекст spark действительно работает с экземпляром notebook с помощью pytest.

Однако, когда я пытаюсь прочитать файл csv в тесте, который я описал выше, я получаю следующую ошибку:

 py4j.protocol.Py4JJavaError: An error occurred while calling o84.csv.
E  : java.lang.RuntimeException: java.lang.ClassNotFoundException: Class 
org.apache.hadoop.fs.s3a.S3AFileSystem not found
 

Как я могу, фактически не загружая никаких файлов csv в S3, протестировать эту функцию?

Я также попытался указать uri S3, используя s3:// вместо s3a:// , но получил другую связанную ошибку : org.apache.hadoop.fs.UnsupportedFileSystemException: No FileSystem for scheme "s3" .

Комментарии:

1. github.com/spulec/moto

2. почему бы просто не использовать file:// и не протестировать локальную FS, пока не будете довольны

3. @stevel потому что тогда я точно не тестирую логику приложения в том виде, в каком она реализована, предпочел бы не вносить изменения в код

4. что ж, модульное тестирование с использованием хранилища s3 (а) сложно настроить и (б) требует больших затрат. одним из ограничений является то, что из-за того, что трудно безопасно предоставить учетные данные любому набору инструментов CI, вы не можете так легко автоматизировать тестирование. Если вы хотите общаться с s3 в локальной системе, используйте соединитель s3a и задайте путь к классу , как обсуждают многие другие публикации SO