"""Tests for the entrypoint.""" from unittest.mock import call from unittest.mock import MagicMock from unittest.mock import patch from extract_sales.templates import SELECT_SALES_BATCH_TEMPLATE import pytest import app @patch('app.logger') @patch('app.os') @patch('app.get_ssh_conn') @patch('app._create_dirs') @patch('app._generate_outfile') @patch('app._split_and_compress_outfile') @patch('app._upload_parts') @patch('app._delete_files') def test_run( mock_delete_files, mock_upload_parts, mock_split_and_compress_outfile, mock_generate_outfile, mock_create_dirs, mock_get_ssh_conn, mock_os, mock_logger ): """Test running the task.""" sales_type = 'distro' batch_id = 'testbatch' raw_dir = '/test/raw' parts_dir = '/test/parts' outfile_path = '/test/raw/outfile.txt' def get_env_var_side_effect(env_var_name): if env_var_name == 'SALES_TYPE': return sales_type if env_var_name == 'BATCH_ID': return batch_id mock_os.environ.get.side_effect = get_env_var_side_effect mock_ssh_conn = MagicMock() mock_get_ssh_conn.return_value.__enter__.return_value = mock_ssh_conn mock_create_dirs.return_value = (raw_dir, parts_dir) mock_generate_outfile.return_value = outfile_path app.run() mock_logger.info.assert_called() mock_logger.error.assert_not_called() mock_create_dirs.assert_called_once_with(mock_ssh_conn, sales_type, batch_id) mock_generate_outfile.assert_called_once_with( mock_ssh_conn, sales_type, batch_id, raw_dir ) mock_split_and_compress_outfile.assert_called_once_with( mock_ssh_conn, outfile_path, parts_dir ) mock_upload_parts.assert_called_once_with( mock_ssh_conn, sales_type, batch_id, parts_dir ) mock_delete_files.assert_called_once_with(mock_ssh_conn, raw_dir, parts_dir) @patch('app.logger') def test_run_error(mock_logger): """Test running the task with an error.""" with pytest.raises(Exception): app.run() mock_logger.error.assert_called_once() @patch('app.os') def test_get_run_params_missing_sales_type(mock_os): """Test getting the run parameters with missing sales_type.""" def get_env_var_side_effect(env_var_name): if env_var_name == 'SALES_TYPE': return None mock_os.environ.get.side_effect = get_env_var_side_effect with pytest.raises(Exception, match='Missing environment variable: `SALES_TYPE`'): app._get_run_params() @patch('app.os') def test_get_run_params_invalid_sales_type(mock_os): """Test getting the run parameters with invalid sales_type.""" def get_env_var_side_effect(env_var_name): if env_var_name == 'SALES_TYPE': return 'invalid_sales_type' mock_os.environ.get.side_effect = get_env_var_side_effect with pytest.raises(Exception, match='Invalid environment variable: `SALES_TYPE`'): app._get_run_params() @patch('app.os') def test_get_run_params_missing_batch_id(mock_os): """Test getting the run parameters with missing batch_id.""" def get_env_var_side_effect(env_var_name): if env_var_name == 'SALES_TYPE': return 'distro' if env_var_name == 'BATCH_ID': return None mock_os.environ.get.side_effect = get_env_var_side_effect with pytest.raises(Exception, match='Missing environment variable: `BATCH_ID`'): app._get_run_params() @patch('app.config') @patch('app.run_ssh_cmd') def test_create_dirs(mock_run_ssh_cmd, mock_config): """Test creating directories.""" mock_config.OUTFILE_DIR = '/test' mock_config.SERVICE_USER = 'testuser' mock_config.SERVICE_GROUP = 'testgroup' mock_ssh_conn = MagicMock() result = app._create_dirs(mock_ssh_conn, 'distro', 'testbatch') mock_run_ssh_cmd.assert_has_calls([ call( mock_ssh_conn, 'install -dv -m 0775 -o testuser -g testgroup /test/distro/testbatch/raw' ), call( mock_ssh_conn, 'install -dv -m 0775 -o testuser -g testgroup /test/distro/testbatch/parts' ) ]) assert result == ( '/test/distro/testbatch/raw', '/test/distro/testbatch/parts' ) @patch('app.config') @patch('app.run_ssh_cmd') def test_generate_outfile(mock_run_ssh_cmd, mock_config): """Test generating the outfile.""" mock_config.SSH_HOST = 'testhost' mock_config.MYSQL_DB_USER = 'testuser' mock_config.MYSQL_DB_PASS = 'testpass' mock_ssh_conn = MagicMock() result = app._generate_outfile(mock_ssh_conn, 'distro', 'testbatch', '/test/raw') expected_query = SELECT_SALES_BATCH_TEMPLATE.render( table_name='dig_sales_testfile_abacus', batch_id='testbatch' ) mock_run_ssh_cmd.assert_called_once_with( mock_ssh_conn, ('mysql -h testhost -u testuser -ptestpass --quick -N' f' -e "{expected_query}" > /test/raw/outfile.txt') ) assert result == '/test/raw/outfile.txt' @patch('app.config') @patch('app.run_ssh_cmd') def test_split_and_compress_outfile(mock_run_ssh_cmd, mock_config): """Test splitting and compressing the outfile.""" mock_config.SPLIT_SIZE = '10G' mock_ssh_conn = MagicMock() app._split_and_compress_outfile( mock_ssh_conn, '/test/raw/outfile.txt', '/test/parts' ) mock_run_ssh_cmd.assert_called_once_with( mock_ssh_conn, ("split -C 10G --filter='/usr/bin/pigz > $FILE.gz'" ' /test/raw/outfile.txt /test/parts/outfile_parts_') ) @patch('app.config') @patch('app.run_ssh_cmd') def test_upload_parts(mock_run_ssh_cmd, mock_config): """Test uploading parts.""" mock_config.S3_BUCKET_NAME = 'testbucket' mock_ssh_conn = MagicMock() app._upload_parts( mock_ssh_conn, 'distro', 'testbatch', '/test/parts' ) mock_run_ssh_cmd.assert_called_once_with( mock_ssh_conn, ('s5cmd cp /test/parts' ' s3://testbucket/extract-sales/distro/testbatch/') ) @patch('app.run_ssh_cmd') def test_delete_files(mock_run_ssh_cmd): """Test deleting files.""" mock_ssh_conn = MagicMock() app._delete_files(mock_ssh_conn, '/test/raw', '/test/parts') mock_run_ssh_cmd.assert_called_once_with( mock_ssh_conn, 'rm -rf /test/raw /test/parts' )