Python for test automation: files
File handling is facilitated through built-in functions and methods provided by the open
function. To read or write to a file, one typically starts by opening it using open
with the desired file mode ('r' for reading, 'w' for writing, 'a' for appending, etc.). Once opened, the file object provides various methods such as read
, write
, readline
, and close
for interacting with the file's contents. Reading from a file involves methods like read
to retrieve the entire content, or readline
to read one line at a time. Similarly, writing to a file can be achieved with the write
method. It's essential to close the file using the close
method after all operations are complete to release system resources. Python also supports file handling in binary mode ('rb', 'wb', etc.) for dealing with non-text files like images or executables. Additionally, the os and shutil modules offer functionalities for file manipulation and management, such as renaming, deleting, or moving files.
Here to open and close a file:
f = open("file.txt", "r")
for line in f:
print(line)
f.close()
Instead of manually closing the file, it is good practice to always use the with-statement to handle opening and closing the file:
with open("file.txt", "r") as f:
for line in f:
print(line)
Here we do not need to manually handle closing the file; that is handled automatically after the indented block has completed running. Using the with-statement also ensures that the file is closed even when an exception is raised by the code running inside the statement.
CSV files
The comma-separated values file format can be used to store test data in a test automation project. Handling CSV files is streamlined through the built-in csv module, offering functionalities for reading from and writing to CSV files. To begin, one typically imports the csv module and utilizes its reader and writer objects to handle CSV file data. For reading, the reader object facilitates easy iteration through each row of the CSV file, with options to specify delimiters, quote characters, and other formatting options. Conversely, the writer object enables efficient writing of data to a CSV file, with similar customization options. Additionally, the DictReader and DictWriter classes allow for working with CSV files where each row is represented as a dictionary, offering more intuitive data manipulation. Python's CSV module seamlessly handles edge cases like handling escaped characters and empty fields, ensuring data integrity.
reader
To read a csv file, we first open it with the open
function, then pass the opened file to the reader
function in the csv
package, which in turn returns a reader object that we can iterate over to go through each line in the csv as a list of values.
import csv
with open("file.csv", "r") as f:
reader = csv.reader(f)
for line in reader:
print(line)
>>>['a', 'b', 'c']
>>>['1', '2', '3']
>>>['4', '5', '6']
>>>['7', '8', '9']
writer
To write a csv file, we first open it with the open
function, then pass the opened file to the reader
function in the csv
package, which in turn returns a writer object that we can use to write individual rows or multiple rows at a time:
import csv
with open("out.csv", "w") as f:
writer = csv.writer(f)
# write a single row
writer.writerow(
["a", "b", "c"],
)
# write multiple rows at once
writer.writerows(
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
)
DictReader
To read a csv file into a list of dictionaries where each dict in the list has key-value pairs so that the keys match the headers in the csv, and the values match a single row in the csv:
import csv
with open("test.csv", "r") as f:
reader = csv.DictReader(f)
for row in reader:
print(row)
>>>{'a': '1', 'b': '2', 'c': '3'}
>>>{'a': '4', 'b': '5', 'c': '6'}
>>>{'a': '7', 'b': '8', 'c': '9'}
DictWriter
To write a csv file from a list of dictionaries, we can use DictWriter:
import csv
with open("out.csv", "w") as f:
data = [
{
"a": 1,
"b": 2,
"c": 3,
},
{
"a": 4,
"b": 5,
"c": 6,
},
{
"a": 7,
"b": 8,
"c": 9,
},
]
# here we specify the fieldnames (header columns) to be the
# keys ('a', 'b' and 'c') found in the first dict in our
# data list
writer = csv.DictWriter(f, fieldnames=data[0].keys())
# write the headers into the opened file
writer.writeheader()
# write the data rows
writer.writerows(data)
JSON files
Handling JSON files is straightforward thanks to the built-in json
module, which provides functionalities for encoding and decoding JSON data. Typically, JSON files are read using the json.load
function, which parses the JSON data from a file object into Python data structures like dictionaries or lists. Similarly, to write Python data back into a JSON file, the json.dump
function is employed, converting Python objects into their JSON representation and storing them in the specified file. Alternatively, json.loads
and json.dumps
functions can be used to work with JSON strings instead of file objects.
load
To read a JSON file into a Python dictionary, we first use the open
function to open the JSON file for reading, then pass the opened file object to the json.load()
function which returns a dictionary or list of dictionaries depending on the content of the JSON file. If we have a JSON file that contains
{
"a": 1,
"b": "hello",
"c": [1, 2, 3],
"d": {
"e": "hi"
}
}
then we can read that file into a Python dictionary as follows:
import json
with open("file.json", "r") as f:
data = json.load(f)
print(data)
>>>{'a': 1, 'b': 'hello', 'c': [1, 2, 3], 'd': {'e': 'hi'}}
dump
Conversely, we can dump the contents of a dictionary into a JSON file (i.e. if the contents of the dictionary are fully JSON encodeable; only strings, numbers, booleans, None (null), and lists and dictionaries containing those values are accepted). Given the dictionary from our previous example {'a': 1, 'b': 'hello', 'c': [1, 2, 3], 'd': {'e': 'hi'}}
, we can dump it into a JSON file using the json.dump()
function as follows:
import json
d = {'a': 1, 'b': 'hello', 'c': [1, 2, 3], 'd': {'e': 'hi'}}
with open("out.json", "w") as f:
json.dump(d, f)
Formatting
When dumping a dictionary into a JSON file, by default it will be written on a single line, which is not ideal for a human to read the contents. We can use the indent argument of json.dump
to format the JSON nicely. For the previous example, if we add indent=2
to the json.dump
call, we get the following output:
{
"a": 1,
"b": "hello",
"c": [
1,
2,
3
],
"d": {
"e": "hi"
}
}