Django 이전에 포스팅을 했던 fixture에 대해서 간단하게 포스팅해보도록 하겠습니다.


환경 및 선수조건


소개

Django에서 fixture를 이용해서 테스팅을 할 때 DB에 값들을 넣는 방법을 알아보겠습니다.

  1. Model을 만든다.
  2. Model을 dump 떠서 혹은 입력을 통해 json형태로 저장한다.
  3. 명령어를 통해서 테스팅 전에 불러온다.


Model을 만들기

기본적으로 Django에서는 [app_name]/models.py의 파일에 작성해주시면 됩니다. 작성해주시고 아래와 같은 migrate 명령어를 주셔야 적용이됩니다.

models.py

from django.db import models


class Meeting(models.Model):
    maker = models.TextField()
    name = models.TextField()
    place = models.TextField()
    start_time = models.DateTimeField()
    image_path = models.ImageField(blank=True)
    distance_near_univ = models.TextField()
    price_range = models.TextField()

$ python manage.py migrate


Model을 dump 떠서 혹은 입력을 통해 json형태로 저장한다.

2가지 방법(Model을 dump 혹은 직접 입력)으로 json을 만들 수 있습니다.


방법1) DB에 있는 model들을 dump 뜨기

우선 현재 db에 있는 data들을 json형식으로 dump를 뜨고 싶다면 아래의 명령어를 통해서 할 수 있다.

$ python manage.py dumpdata [app_name].[model.name] --indent [INDENT] > [fixture_name].json

실제 사용 코드는 아래와 같습니다.

$ python manage.py dumpdata moim.meeting --indent 2 > meeting-data.json


방법2) 직접 json 파일을 작성하기

위에 처럼 현재 db가 아니라 아래의 형태처럼 직접 db를 json형식으로 입력해도 됩니다. json형식에 대한 부분은 구글에 자료가 많으니 따로 작성하지 않겠습니다.

[
    {
    "model": "moim.meeting",
    "pk": 1,
    "fields": {
        "maker": "test maker",
        "name": "test name",
        "place": "test place",
        "start_time": "2017-02-19T08:09:29Z",
        "image_path": "",
        "distance_near_univ": "test univ",
        "price_range": "233000~335000"
        }
    }
]


만든 json파일을 [app_name]/fixtures 폴더로 이동

결론적으로 위의 형태를 만족하는 json형태의 파일을 생성하고 [app_name]폴더 아래 fixtures라고 폴더를 만들어주시고 넣어주시면 됩니다.


명령어를 통해 테스팅 전에 불러오기

이제 테스팅을 위해서 json파일들을 db에 넣어보겠습니다. 아래의 명령어를 통해서 실행합니다.

$ python manage.py migrate
$ python manage.py loaddata [app_name]/fixtures/[fixture_name].json
$ python manage.py runserver

제가 실제 사용한 명령어는 아래와 같습니다.

$ python manage.py migrate
$ python manage.py loaddata moim/fixtures/meeting-data.json
$ python manage.py runserver

Django admin을 통해서 자료가 들어가 있음을 확인 할 수 있습니다.

pytest 혹은 테스팅을 할 때 fixture란게 어떤 개념이고 그에 대한 간략한 예시를 알아보기로 한다.


환경 및 선수조건

  • Python
  • Pytest가 무엇인지
  • Django에 대한 기본 사용 및 이해
  • Selenium


소개

pytest에 대한 공부를 하면서 계속 fixture라는게 나오고 mocking 혹은 mock object라는 것이 계속 나오다가 이해를 하지 못하였는데 이 기회에 정리하면서 이해를 해보고자 정리합니다.

살펴 볼 fixture라는게 어떤 개념인지부터 시작해 현재 프로젝트에 적용해본 pytest fixture의 예시를 보도록 하겠습니다.


Fixture가 무엇인가요?

우선 fixture의 사전적 정의에 대해서 살펴보고 넘어가보도록 하겠습니다. 검색은 네이버에서의 결과입니다.

naver fixture meaning

사전적인 의미로는 경기 혹은 고정 세간이라도 나와있지만… 아직은 무슨 의미인지 감이 안옵니다…(그게 정상) 그러면 Wikipedia에 한번 영어로 검색을 해보겠습니다.

wiki fixture search

검색을 해보니 첫번째에 Test fixture라는 부분이 있습니다. 의미는 “used to control and automate testing”으로 테스트를 자동화 하거나 조절하기위해 사용된다고 합니다.

링크를 들어가 보시면 아래와 같이 소프트웨어 섹션이 있습니다.

wiki fixture software

간략하게 요약을 하면 fixture란 테스팅을 하는데 있어서 필요한 부분들을 혹은 조건들을 미리 준비해놓은 리소스 혹은 코드들이라고 보면됩니다. DB가 필요해서 어떤 내용들을 테스트 할 때만 DB에 넣어서 확인을 한다던가 특정 파일을 테스팅 할 때 필요하다면 특정 파일들이 그 fixture라고 볼 수 있습니다.


pytest에서 fixture 사용하기

이제 fixture에 대해서 개념을 알았으니 실제로 간단한 코드를 보도록 하겠습니다. pytest를 통해서 테스팅을 할 때 특정 browser를 만들고 그 브라우저를 계속 사용하기위한 코드입니다. 즉 여기서는 browser가 fixture가 되겠죠?


homepage_test.py

@pytest.fixture(scope="module")
def browser():
    # ...
    # 브라우저를 받아오는 부분
    # driver는 webDriver이다.
    # ...
    yield driver
    driver.close()

def test_first_page_card_title(browser):
    browser.get("http://localhost:8000")
    assert '규카츠 먹을래?' in browser.page_source

browser함수에서 driver를 만들고 그 driver를 test_first_page_card_title이라는 함수가 사용을 합니다.

위에 @pytest.fixture(scope="module")을 통해서 현재 py파일 안에서 계속 사용할 것임을 명시 하였기에 현재 py파일에서 실행이 되면 계속 driver를 사용 할 수 있게됩니다.

추가적으로 아래처럼 계속 browser를 사용해도 하나의 브라우저를 사용할 수 있으며 yield예약어가 있기 때문에 다 끝났을 때 browser의 driver.close()가 실행됩니다.


def test_1(browser):
    browser.get("http://localhost:8000")
    assert True

def test_2(browser):
    browser.get("http://localhost:8000")
    assert True

def test_f3(browser):
    browser.get("http://localhost:8000")
    assert True        

다시 마지막으로 정리하면 fixture란 테스팅에서 쓰이는 값이나 리소스에 대한 부분으로 미리 준비해두는 준비 도구 및 재료입니다. 그 값은 어떤 객체가 될수도 있고 환경도 될수도 있고 DB가 될수도 있습니다.

다음에는 fixture 혹은 RunPython을 이용해서 pytest에서 테스팅 하기위한 DB를 어떻게 설정하는지를 확인해보는 코드를 만들어보겠습니다.

업데이트(2018.04.16): 내용을 조금 수정하였습니다.

python에서 HttpResponse를 이용해 간단하게 Http요청 응답을 테스트하는 방법을 알아보자


환경 및 선수조건

  • Python
  • Django에 대한 기본 사용 및 이해
  • Selenium


소개

TDD를 공부하면서 프로젝트를 진행하기 때문에 현재 어떠한 일들을 구현할 때 기능 테스트를 하게된다. 그러한 기능 테스트를 진행하면서 이제 Http요청을 보내고 응답을 하였을 때 그 응답의 결과에 어떠한 특정한 문자열이 있는걸 확인할 때 본인은 html을 직접 만들어서 template를 만들고 응답해주는 코드를 작성하려 하였는데 더 쉬운 방법이 있어서 포스팅을 하려고 한다.


HttpRequest와 HttpResponse는?

  • HttpRequest: 요청에 대한 메타정보를 가지고 있는 객체
  • HttpResponse: 응답에 대한 메타정보를 가지고 있는 객체


상황 가정

홈페이지를 열었을 때 “돈까스 모임”이라는 모임의 텍스트가 있어야 한다고 가정을 하고 selenium을 통해 테스트를 해봅시다.


HttpResponse에 대한 예제 및 테스트

urls.py 코드 작성

urls.py는 장고에서 특정 url에 대한 요청을 어떤 함수나 클래스로 매핑해서 연결시켜주는 역할을 하는 부분입니다. 여기에서는 어떤 요청이던지간에 views.homepage의 함수로 연결되게 해두었습니다.

urls.py

from django.conf.urls import url
from django.contrib import admin
from moim import views

urlpatterns = [
    url(r'^$', views.homepage, name='home'),
    url(r'^admin/', admin.site.urls),
]


views.py 코드 작성

views.py는 urls.py에서 라우팅 되어온 요청에 대해서 처리하고 그에 따른 결과를 응답해주는 부분이 작성되는 곳입니다.

views.py

from django.shortcuts import render
from django.http import HttpResponse


def homepage(request):
    return HttpResponse('돈까스 모임')


테스트 코드 작성

이제 urls.py에서 views.py의 특정 함수(이 본문의 경우에는 homepage 함수)로 연결해주고 views.py의 homepage 함수에서 “돈까스 모임”이라고 응답을 해주므로 이제 확인하는 테스트 코드를 작성해보겠습니다.

homepage_test.py

def test_checking_prepared_environment_with_selenium():

    #드라이버를 설치하고 가져오는 코드
    driver.get("http://localhost:8000")
    assert '돈까스 모임' in driver.page_source
    driver.close()


테스트 및 실행

장고 서버를 실행시키고 테스트를 돌려보도록 하겠습니다.

$ python manage.py runserver # 장고 서버 실행
$ pytest homepage_test.py # 테스트 코드 실행


다음처럼 테스트가 성공적으로 실행됨을 확인 할 수 있습니다.

Done Test


참고자료

업데이트(2019.02.19): 파일열기모드 관련 내용 추가

python에서 with문의 용도와 쓰임을 알아보자


소개

기본적으로 거의 모든 프로그래밍 언어가 파일 입출력을 지원하며(어찌보면 당연한 이야기인가?…) 그러한 파일 입출력을 할 때 해당 파일을 위해 open과 close를 해줘야한다.

그러한 부분이 python에도 존재하며 혹시나 우리가 했을 법한 실수인 close를 해주는 부분을 빼먹을 수도 있기에 하나의 with문으로 묶어서 사용 할 수 있다.


기본적인 사용법

  • 기본적인 사용법은 with expression as target: suite의 형태로 사용하면 된다.


다음 아래와 같은 코드를

file_data = open('file.txt')
print(file_data.readline(), end="")
file_data.close()

아래처럼 바꿀 수 있다.

with open('file.txt') as file_data:
    # 기본적으로 사용하는 함수를  with문 안에 사용하면 되며
    # with문을 나올 때 close를 자동으로 불러줍니다.
    print(file_data.readline(), end="")


파일 열기 모드

  • 파일열기모드: 파일열기모드란 파일을 Binary형태로 읽을지 아니면 인코딩단위로 읽을지, 파일을 읽을건지 쓸건지 아니면 동시에 할건지에 대한 부분을 정하는 지시자라고 볼 수 있습니다.

  • r: 읽기 모드, 파일을 읽을 때 사용합니다.
  • w: 쓰기 모드, 파일에 쓸 때 사용하며 파일이 이미 동일한 이름으로 존재한다면 덮어씁니다.
  • a: 추가 모드, 존재하는 파일에 추가할 때 사용하며 파일이 없다면 생성합니다.
  • r+, w+, a+: 읽기모드 + 쓰기모드, w+a+의 차이는 위와 같습니다.
  • rb, wb, ab, rb+, wb+, ab+: 각각의 모드들은 위와 동일하나 Binary 포맷으로 읽거나 쓰는걸 진행합니다.

쓰기(Write)

with open('file.txt', 'w') as file_data:
    file_data.write("First\n")
    file_data.write("Second")

읽기(Read)

with open('file.txt', 'r') as file_data:
    for line in file_data:
        print(line)

추가(Append)

with open('file.txt', 'a') as file_data:
    file_data.write("Third\n")


참고자료

pytest를 설치는 하였고 이제 Exception을 처리하는 방법에 대해서 알아보자


환경 및 선수조건


기본적인 사용법

  • Exception의 오류를 잡기 위해서 pytest에서는 pytest.raises([Exception])이라는 함수를 통해서 실행시킵니다. 바로 코드를 보도록 하겠습니다.
  • 아주 간단한 코드로 with문을 참고하시면 ()안에 있는 Exception이 발생하는지를 확인하는 코드입니다. with문 안에 1/0의 코드를 통해서 해당 Exception을 발생시킵니다.

test_zero_division.py

import pytest


def test_zero_division():
    # with문 괄호에 있는 Exception이 해당 block에서 일어나는지 확인하는 코드
    with pytest.raises(ZeroDivisionError):
        1 / 0


이제 코드를 작성하였으니 실행시켜봅시다.

Run Test


참고자료