0

I have a POST endpoint with fastapi that goes a little like this. This takes in an excel file and turns it into a pandas dataframe.

@router.post(
"/endpoint/upload_excel",
status_code=status.HTTP_200_OK
)
async def upload_excel(user_excel_file: UploadFile = File(...)):
     """
     read user Excel file from multipart/form-data into pd dataframe
     """

user_excel_bytes = await user_excel_file.read()
user_excel_bytes_io = io.BytesIO(user_excel_bytes)
user_lineage = pd.read_excel(user_excel_bytes_io)

This function continues to manipulate the pandas dataframe, such as sorting columns, checking for nulls, and checking data types.

How could I test this function with pytest in python? I believe I need to mock the the multipart/form-data (user_excel_file: UploadFile = File(...)). I want to test for the edge cases like catching nulls or having ints where strings should be, but I don't want to create a separate test excel file for each case.

If the input to this function was a pandas dataframe, I could easily mock that! But how can I mock the input excel?

5
  • 1
    If I'm understanding you correctly (please say if this doesn't answer your question). You can avoid creating real Excel files by creating an in-memory Excel file using pandas and io.BytesIO, then wrapping it in a FastAPI UploadFile mock. This lets you mock any Excel content dynamically without creating real files. You just build a DataFrame for each edge case and convert it to a mock UploadFile. Commented Oct 23 at 20:59
  • @ninadepina That sounds like what I want! Do you know any resources on how to create an in-memory Excel file with pandas and io.BytesIO? Commented Oct 23 at 21:20
  • I can't quickly find one source that explains it all.. You should puzzle some sources together. The links I found in the few minutes of googling: Some Medium source about simplifying file exports with bytesio and pandas and Another stack overflow issue Commented Oct 23 at 21:39
  • I'd be most tempted to keep a collection of Excel files and iterate through 'em, even if you dynamically generate some, especially because this enables collecting test cases Commented Oct 23 at 22:11
  • 1
    The easiest solution is to stick excel-files that are examples of what you want as fixtures somewhere, then use the built-in testclient in FastAPI to submit them to your endpoint. There is no need to mock or generate anything; use real dependencies and examples that show what you want to test. Commented Oct 24 at 11:57

1 Answer 1

0

Create DataFrames in tests and convert to excel bytes without like real file:

import io
import pandas as pd

def df_to_excel_bytes(df):
    buf = io.BytesIO()
    df.to_excel(buf, index=False)
    buf.seek(0)
    return buf.read()

def test_nulls():
    df = pd.DataFrame({"name": ["Alice", None]})
    response = client.post(
        "/endpoint/upload_excel",
        files={"user_excel_file": ("test.xlsx", df_to_excel_bytes(df))}
    )

For fake data I use Faker.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.