Biblioteka Faker. Generowanie danych testowych z wykorzystaniem Pythona. Przewodnik.

10.2023 | faker | testowanie | python

Dostępna w Pythonie, biblioteka Faker, to proste w obsłudze rozwiązanie programistyczne, które pozwala nam na generowanie danych testowych wg naszych potrzeb. Niniejszy artykuł opisuje podstawowe metody i przypadki użycia, związane z biblioteką Faker.



Spis treści:


 

1. Wprowadzenie

Tworzenie i wykorzystanie danych testowych, jest nieodłączną częścią procesu poznawania narzędzi analitycznych, takich jak Microsoft Power BI, czy też testowania i nauki bibliotek programistycznych z rodziny Data Science.

Ręczne “tworzenie” danych testowych może być czasochłonne i podatne na błędy, dlatego warto korzystać z narzędzi, które umożliwiają generowanie danych testowych automatycznie. Jednym z popularnych narzędzi w tym zakresie jest biblioteka Faker, udostępniona w ramach Pythona.

Dygresja => Oczywiście jest dużo serwisów, które umożliwiają wygenerowanie gotowych danych, dokładnie wg życzenia i bez zbędnego kodowania. Ale jest to czasem związane z kosztem i nie zawsze mamy możliwość wygenerowania takiego zestawu jak potrzebujemy.

W tym artykule sprawdzimy, jak można używać biblioteki Faker do generowania danych testowych pod narzędzia/biblioteki analityczne. Przeprowadzimy przykład generowania danych pod zestaw typu e-commerce.

Zaczynamy….


 

2. Instalacja biblioteki Faker

Zanim zaczniemy korzystać z biblioteki Faker, musimy ją zainstalować. Możemy to zrobić za pomocą menedżera pakietów dla języka Python. Wystarczy wpisać poniższą komendę w terminalu:

pip install faker

Po zainstalowaniu biblioteki Faker, jesteśmy gotowi do rozpoczęcia generowania danych testowych.


 

3. Lista dostępnych metod w Faker

Biblioteka Faker oferuje mnogość funkcji, które umożliwiają generowanie danych testowych w różnych formatach.

Tip. Aby wygenerować listę dostępnych metod w danej bibliotece, można wykorzystać funkcję dir(). Poniżej ilustruje to przykład dla omawianej biblioteki Faker:


from faker import Faker

fake = Faker(['pl-PL'])

Faker.seed(12)

# Pobierz listę wszystkich metod dostępnych dla obiektu `fake`
methods = dir(fake)

# Wydrukuj listę metod
for method in methods:
print(method)

Warto zwrócić uwagę na fragment:

fake = Faker(['pl-PL'])

Czyli kod, który inicjalizuje instancję biblioteki Faker z językiem polskim.

Wykorzystując konkretny język, jak w tym przypadku pl-PL, dane będą generowane w formacie właściwym dla danego kraju i będą miały charakterystykę typową dla tego języka/regionu. W skrócie, ten kod pozwala generować dane w języku polskim np. Polskie nazwisko czy nazwę ulicy.

Kolejny fragment wymagający wyjaśnienia to:

Faker.seed(12)

Metoda Faker.seed() jest używana do inicjalizacji globalnego generatora liczb pseudolosowych w bibliotece Faker. Dzięki temu, gdy podamy konkretną wartość jako ziarno (seed), generator Faker będzie produkować te same pseudolosowe dane za każdym razem, gdy jest używany z tym samym ziarnem.

Jest to przydatne, gdy chcemy uzyskać powtarzalne wyniki podczas generowania fałszywych danych, co może być szczególnie użyteczne w testach jednostkowych czy w innych sytuacjach, gdzie powtarzalność jest ważna.

Przykład


Faker.seed(1234)

fake = Faker()

# Za każdym razem, gdy uruchomimy ten kod, z tym samym ziarnem, dostaniemy to samo imię
print(fake.name())

 

4. Dane osobowe

Zacznijmy zatem od przeglądu metod, pozwalających nam wygenerować dane osobowe.

Lista dostępnych metod:

Identyfikacja

  • name: Generuje imię i nazwisko
  • first_name: Generuje imię
  • last_name: Generuje nazwisko
  • prefix: Generuje przedrostek (np. "Mr.", "Dr.")
  • suffix: Generuje sufiks (np. "Jr.", "III")

Kontakt

  • email: Generuje adres e-mail
  • phone_number: Generuje numer telefonu
  • cell_phone: Generuje numer telefonu komórkowego

Adres

  • address: Generuje pełny adres
  • building_number: Generuje numer budynku
  • street_name: Generuje nazwę ulicy
  • city: Generuje nazwę miasta
  • postcode: Generuje kod pocztowy
  • country: Generuje nazwę kraju

Zatrudnienie

  • job: Generuje nazwę stanowiska / zawód
  • company: Generuje nazwę firmy

Inne

  • date_of_birth: Generuje datę urodzenia
  • gender: Generuje płeć ("Male", "Female")

W kolejnych punktach, przyjrzyjmy się zatem wybranym przypadkom użycia.


 

4.1. Wygenerowanie imienia i nazwiska

name = fake.name()

print(name)

Przykładowe rezultaty:

  • Agnieszka Sądej
  • Tola Kudlak
  • Leonard Kulisz
  • pan Aleks Kryza

Wyniki generowane przez metodę name() mają jednak pewną wadę, która dla mnie dyskwalifikuje tą metodę. Otóż, jak można zobaczyć wyżej, do niektórych osób jest doczepiany przedrostek typu pan / pani.

Dlatego aby wygenerować zestaw typu imię + nazwisko, polecam wykorzystać poniższy kod, który generuje zestawienie bez zbędnych tytułów i z uwzględnieniem płci:


# definicja metody, generującej dane bez prefixu pan / pani

def get_name_without_prefix():

    name = fake.name()
    name_parts = name.split(' ')

    if len(name_parts) > 1:
        if name_parts[0].lower() in ['pan', 'pani']:
            name_parts = name_parts[1:]  # remove prefix
    return ' '.join(name_parts)

# przykładowa lista
for _ in range(10):
  print(get_name_without_prefix())

Przykładowe wyniki:

  • Robert Hudzik
  • Olga Knysak
  • Juliusz Klimko
  • Damian Sporek
  • Juliusz Opyrchał
  • Karol Raczkiewicz
  • Iwo Sajnóg
  • Mieszko Loba
  • Dorota Matraszek
  • Alex Druszcz

 

4.2. Generowanie losowych adresów email

Biblioteka Faker pozwala nam nie tylko wygenerować email, ale nawet wybrać jaki typ emaila chcemy wygenerować:

  • fake.company_email() => generuje adres email w domenie "jak firmowa" np. Pphu.org, chylak.pl
  • fake.free_email() => generuje adresy email w domenach typowych dla darmowych kont email np. Interia.pl, gmail.com, yahoo.com

Przykład. Wygenerowanie listy emaili firmowych


# adres email => firmowy
for _ in range(8):
  print(fake.company_email())

Przykładowa lista wygenerowanych emaili firmowych:

  • yzdziech@hrabia-bejma.net
  • igorboduch@grupa.org
  • mbasista@chylak.pl
  • natanzietal@fundacja.pl
  • leoncholewka@stowarzyszenie.net
  • wyrostekcyprian@frankowicz-jezior.com
  • oliwierzegar@ppuh.org
  • olchawaanna-maria@fundacja.org

Przykład. Wygenerowanie listy emaili darmowych


# adres email => personalny (w darmowej domenie)
for _ in range(8):
  print(fake.free_email())

Przykładowa lista wygenerowanych emaili darmowych:

  • vdoroszuk@interia.pl
  • ngoraj@onet.pl
  • kornel87@hotmail.com
  • ryszardhorbacz@gmail.com
  • olszowajakub@hotmail.com
  • dysdagmara@gmail.com
  • pnazimek@interia.pl
  • dopyrchal@yahoo.com

 

4.3. Generowanie losowych numerów telefonów

Przykład generowania listy numerów telefonów:


# numer telefonu
for _ in range(5):
  print(fake.phone_number())

Przykładowe, wygenerowane numery:

  • +48 699 406 691
  • +48 503 985 569
  • 660 200 168
  • 696 153 448
  • +48 579 913 896

Jeżeli jednak chcemy wygenerować tylko pewien typ numerów np. Numery komórkowe, charakterystyczne dla naszego kraju, to musimy napisać trochę więcej kodu.

Poniżej przykład wygenerowanie numerów testowych - komórkowych - charakterystycznych dla Polski:


def generate_polish_mobile_number(fake):
    first_digit = random.choice([5, 6, 7, 8])
    remaining_digits = [random.randint(0, 9) for _ in range(8)]
    mobile_number = f"+48 {first_digit}{''.join(map(str, remaining_digits))}"
    return mobile_number

fake = Faker(['pl_PL'])

# Import the random module
import random

# Generate 5 Polish mobile numbers
for _ in range(5):
    print(generate_polish_mobile_number(fake))

Wynik powyższego skryptu to:

  • +48 586639271
  • +48 728427654
  • +48 746647711
  • +48 812735475
  • +48 666982303

Mamy więc gotową listę typowo polskich numerów komórkowych z prefixem +48.


 

4.4. Generowanie adresu

Do wygenerowania adresu wykorzystujemy następujące metody:

  • fake.city()
  • fake.street_address()
  • fake.postalcode()

Zdefiniujmy zatem metodę, która wygeneruje nam pełny rekord adresowy tzn. Ulica, kod pocztowy i miasto.


# definiujemy indywidualną metodę, która wygeneruje pojedynczy, pełny adres w postaci ulica, kod pocztowy, miasto
def generate_address_line():
    street_name = fake.street_address()
    postal_code = fake.postcode()
    city = fake.city()
    return f"{street_name}, {postal_code}, {city}"

# generujemy dane adresowe
for _ in range(5):
  print(generate_address_line())

Wyniki tak otrzymane wyglądają następująco:

  • aleja Krasińskiego 36, 69-716, Lubartów
  • pl. Tylna 018, 74-698, Piekary Śląskie
  • pl. Łąkowa 754, 22-140, Sopot
  • plac Chopina 706, 47-293, Sieradz
  • al. Mazurska 224, 83-034, Biłgoraj

Otrzymujemy zatem całkiem dobrze wyglądające dane adresowe.


 

4.5. Generowanie loginu użytkownika

W niektórych zadaniach jako login użytkownika, jest wykorzystywany nie adres email, ale podana nazwa, składająca się z przykładowych liter oraz cyfr.

Aby wygenerować takie nazwy, można wykorzystać następujący skrypt:


# generujemy login
for _ in range(5):
  print(fake.user_name())

Przykładowe wyniki:

  • bmakosz
  • natan66
  • zszajek
  • alanmalysiak
  • juliuszchwala

 

5. Generowanie danych ecommerce

 

5.1. Wygenerowanie numerów zamówień w sklepie

Aby wygenerować numery zamówień w sklepie, należy wykorzystać poniższą metodę:


import random

def generate_random_string():
    return ''.join([str(random.randint(0, 9)) for _ in range(9)])

for _ in range(5):
   print(generate_random_string())

Nie korzystamy tu z Faker, ale z generatora liczb losowych.

Otrzymane wyniki to:

  • 488468586
  • 683815102
  • 340321785
  • 502257050
  • 687391345

 

5.2. Wygenerowanie numerów NIP

Do wygenerowania numeru NIP wykorzystujemy metodę fake.nip().

Przykład:


# generujemy numer nip
for _ in range(5):
  print(fake.nip())

Otrzymane rezultaty:

  • 4248054244
  • 3490840021
  • 3322343345
  • 1259157839
  • 6331802682

 

5.3. Generowanie losowych dat

Do generowania losowych dat można wykorzystać metodę date().

date = fake.date()

print(date)


 

5.4. Pełny rekord zamówienia

Wygenerujmy zatem pełen rekord zamówienia, który będzie miał postać typu:

ID,order_id,customer_name,customer_email,order_value,purchased_items,delivery_cost,payment_method,delivery_method

W tym celu wykorzystajmy poniższy skrypt:

=> Skrypt generuje 10k linijek z danymi testowymi

=> skrypt przyjmuje jako parametr ilość produktów, które może zakupić użytkownik, w ramach jednego zamówienia. Domyślnie jest to jeden produkt per zamówienie


# dane wyjściowe zostaną zapisane w pliku tekstowym ecommerce_data.csv
def generateOrderList(numberOfProducts=1, dateStart=datetime(2021, 1, 1), dateEnd= datetime(2022, 1, 1)):
    with open('ecommerce_data.csv', 'w', newline='') as file:
        writer = csv.writer(file)

        # nagłówek naszego pliku z danymi
        writer.writerow(["ID", "order_id", "order_date", "customer_name", "customer_email", "order_value", "purchased_items", "delivery_cost", "payment_method", "delivery_method"])

        # liczba rekordów jakie generujemy w pętli
        for i in range(1, 10001):
            # generuje losową datę w podanym przedziale czasu
            random_date = fake.date_between_dates(dateStart, dateEnd)

            # wartość zamówienia
            order_value = random.randint(100, 3000)

            # koszt dostawy zamówienia
            delivery_cost = random.randint(10, 50)

            #liczba zakupionych elementów
            purchased_items = random.sample(items, numberOfProducts) if numberOfProducts > 1 else random.choice(items)

            # zapis danych do pliku
            writer.writerow([i, i+10000, random_date, get_name_without_prefix(), fake.email(), order_value, str(purchased_items), delivery_cost, random.choice(payment_methods), random.choice(delivery_methods)])

Wywołanie skryptu:

generateOrderList()

Wygeneruje nam - jako rezultat - plik z następującymi danymi:

ID,order_id,order_date,customer_name,customer_email,order_value,purchased_items,delivery_cost,payment_method,delivery_method

1,10001,2021-03-29,Kazimierz Deszcz,marcelpodpora@example.net,2149,Mikser ręczny,49,PayPal,Standardowa dostawa

2,10002,2021-01-24,Julian Krzysiek,alan86@example.com,1436,Odkurzacz,15,PayU,Przesyłka priorytetowa

3,10003,2021-10-01,Nela Ciak,qjaszcz@example.com,2347,Robot sprzątający,10,Przelewy24,Przesyłka ekspresowa

4,10004,2021-07-09,Jeremi Sowała,vdanieluk@example.com,120,Czajnik,11,Apple Pay,Przesyłka ekspresowa

5,10005,2021-04-17,Roksana Szklarek,nkwasek@example.org,2857,Blender,36,Apple Pay,Przesyłka priorytetowa

6,10006,2021-11-05,Jakub Kruzel,bpolom@example.net,130,Zamrażarka,32,TPay,Przesyłka priorytetowa


 

6. Tworzenie danych dla konkretnej dziedziny np. Nazwa zawodu

Biblioteka faker umożliwia również tworzenie danych pod konkretne dziedziny np. Można tworzyć listę zawodów.

Przykład kodu:


for _ in range(5):
  print(fake.job())

Przykładowe rezultaty:

  • Rzeczoznawca majątkowy
  • Kontroler biletów
  • Technik weterynarii
  • Broker
  • Dubler

Jak zatem widać, otrzymujemy całkiem ładną listę zawodów.


 

7. Generowanie danych testowych w różnych formatach

Biblioteka Faker umożliwia generowanie danych testowych w różnych formatach, takich jak CSV, JSON, SQL, XML itp. Dzięki temu możemy łatwo dostosować generowane dane do wymagań naszych narzędzi analitycznych.

 

7.1. Przykład 1. Generowanie danych testowych w formacie CSV

Skrypt generujący proste dane testowe z zapisem tych danych w pliku csv:


from faker import Faker
import csv

fake = Faker()

with open('test_data.csv', 'w', newline='') as file:

writer = csv.writer(file)
writer.writerow(['Name', 'Email', 'Phone Number'])

for _ in range(10):
  name = fake.name()
  email = fake.email()
  phone_number = fake.phone_number()

writer.writerow([name, email, phone_number])


 

7.2. Generowanie danych testowych w formacie JSON

Skrypt, generujący proste dane testowe z zapisem tych danych w formacie json:


import json

data = []

for _ in range(10):
    name = fake.name()
    email = fake.email()
    phone_number = fake.phone_number()
    data.append({
        'name': name,
        'email': email,
        'phone_number': phone_number
    })

    with open('test_data.json', 'w') as file:
      json.dump(data, file)


 

7.3. Generowanie danych testowych w formacie SQLite

Skrypt, generujący proste dane testowe z zapisem tych danych w formacie SQLlite:


import sqlite3 
from faker import Faker

fake = Faker()

# Utwórz połączenie z bazą danych SQLite i kursor
conn = sqlite3.connect('test_data.db')
cursor = conn.cursor()

# Utwórz tabelę, jeżeli nie istnieje
cursor.execute('''
CREATE TABLE IF NOT EXISTS test_data (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT,
    email TEXT,
    phone_number TEXT
);
''')

conn.commit()

# Generuj dane i dodaj je do bazy danych
for _ in range(10):
    name = fake.name()
    email = fake.email()
    phone_number = fake.phone_number()
    cursor.execute("INSERT INTO test_data (name, email, phone_number) VALUES (?, ?, ?)", (name, email, phone_number))

    conn.commit()

# Zamknij połączenie z bazą danych
conn.close()


 

8. Kody źródłowe

Poniżej znajduje się lista linków do Github Gist, gdzie można zobaczyć pełny kod omawianych przykładów.


 

9. Podsumowanie

W niniejszym artykule pokazaliśmy wykorzystanie biblioteki Faker do generowania danych testowych, w szczególności mogliśmy zobaczyć jak wygenerować pełny zestaw danych testowych dla serwisu typu e-commerce, czyli zestaw transakcji.


 

Uwaga prawna

W niniejszym artykule pojawiły się przykłady danych testowych, wygenerowanych przez bibliotekę Faker. Nie wykluczam, że dane te są podobne do rzeczywistych osób czy podmiotów. Jeżeli tak, to jest to czysty przypadek I nie należy wyciągać tutaj daleko idących wniosków.