Mock Your CSV: The Simple Way



Hey guys! It's me again! The, you know who (and if you don't know, read who's the author please).


I've been working on test heavy task on this project lately and now I want to share you guys on how I solve one of my problems, how to mock file input (in this case CSV)? It started when my task requirement needs me to create a method that validates a CSV file input whether it contains the valid attributes or not. On our test driven development approach, I need to create the test and stub first to construct a clearer picture of what should I have to do right? But the test is a bit tricky because the input of the implementation is a file passed from the frontend-kind-of-form via the API. So, how do I test the method? How do I get the data?

Lemme think for a second.

Well, for sure, I need to mock the file, you know, create a fake file that imitates the real data. But, in what form? I don't want to write a real CSV file into our project directory, can I just make an object? Like, file object?

After a short research on the internet, StringIO is a python pre-installed module that I'm looking for! In short, StringIO a file-like object (buffer), so I can use it to create a CSV file-like object.
Now what?

It's 101 time!

StringIO is a package from io, don't forget to import the package.
We're going to construct a CSV data, what do we need? Python also provides us a CSV package for constructing a CSV data, also you can explore Pandas for more advanced CSV creating tools using dataFrame.

1
2
import csv
from io import StringIO

Writing file to StringIO is quite similar to writing a file to file output, but one you might notice that StringIO is opened at instantiation so you don't need to open it first. For the sake of simplicity, I will only demonstrate the easiest CSV data mock requirement on our project, territory.


1
2
3
4
file = StringIO()
writer = csv.writer(file)
writer.writerow(['id', 'Province', 'City', 'Subdistrict', 'Village'])
writer.writerow([1, 'DKI Jakarta', 'Jakarta Timur', 'Duren Sawit', 'Malaka Jaya'])

Done! Easy right? But not so fast. If you try to take the value from the StringIO literally, you will get, nothing! But why?

I will explain just a little bit. So you can imagine the way StringIO works is like you writing a file on a notepad. It has a pointer pointing at the end of a file so it can append new write input to the next line. How StringIO read the file is quite similar, it will try to read the data ahead. So at the current state, what data is ahead of our pointer? Nothing. So you have to move the pointer backward and in short, move the pointer to the very first line so we can read all of the data. Don't be panic, it just a line of code, luckily!


1
file.seek(0)

Now our mock is ready to use! Just put it into our stub, write our expected return on the test, and assert the result. Job well done!
Here I summarize what can we learn from this post and a reference for anyone who thirsts for knowledge:
Wait a minute, but isn't there any package out there that will do some magic to solve this problem?

There are many ways to mock a file, and there are also some packages that will help you, but I still could find any magic that satisfies my requirement because I need a customized CSV structure with unusual value. So better make it by my self that wasting my time searching the web.

That's it, that's it. See you later guys!

0 komentar:

Post a Comment