문제상황
해결방법
적용과정
pip install pytest
*models.py에는 test_model.py,test_service.py,test_view.py에 공통적으로 쓸 함수를 작성
*test_model.py에는 model계층을 테스트하는 코드를 작성
*test_service.py에는 service계층을 테스트하는 코드를 작성
*test_view.py에는 view계층을 테스트하는 코드를 작성
def test_get_user_info(user_service):
#1번 유저 정보 확인
user_info=user_service.get_user_info(1)
#방식1
assert user_info=={
'email':'test@test.com',
'name':'test',
'id':1
}
#방식2
assert user_info==get_user_info(1)
#존재하지 않는 유저 정보 확인
user_info=user_service.get_user_info(100)
assert user_info==None
*위는 db상의 정보를 불러오는 것이므로 하드하게 비교하는 방식 1보다 이미 검증된 데이터를 가져오는 get_user_info함수를 미리 선언하여 방식2처럼 작성정보를 수정 및 삭제하는 기능은 기존의 데이터를 미리 확인하고 변환할 데이터와 직접 비교
ex)
def test_update_user_info(user_service):
#업데이트 하려는 유저의 기존 정보 미리 확인
user_info=get_user_info(1)
assert user_info=={
'id':1,
'name':'test1',
'email':'test1@naver.com',
'profile':'testuser1'
}
#업데이트 항목 설정
update_user={
'name':'updateuser1',
'profile':'updatetestuser1'
}
#유저 업데이트 result=user_service.update_user_info(1,update_user)
assert result==2
user_info=get_user_info(1)
assert user_info=={
'id':1,
'name':update_user['name'],
'email':'test1@naver.com',
'profile':update_user['profile']
}
*위는 db상에 유저의 데이터가 수정이 되었기 때문에 변환시켜준 데이터로 직접 비교
import sys,os
sys.path.append((os.path.dirname(os.path.abspath(os.path.dirname(__file__)))))
import config
from sqlalchemy import create_engine,text
database=create_engine(config.test_config['DB_URL'],encoding='utf-8',max_overflow=0)
def get_user_id_and_password(email,type):
result=database.execute(text("""
select
id,
hashed_password
from users
where email=:email
and type=:type
"""),{'email':email,'type':type})
row=result.fetchone()
result.close()
user_id_and_password={
'id':row['id'],
'hashed_password':row['hashed_password']
} if row else None
return user_id_and_password
def get_room_userlist(room_id):
rows=database.execute(text("""
select
r_u.user_id as id,
u.name,
u.email,
u.profile
from rooms_user_list as r_u
left join users as u
on r_u.user_id=u.id
where r_u.room_id=:room_id
and u.deleted=0
and r_u.deleted=0
"""),{
'room_id':room_id
}).fetchall()
...
*test_model.py,test_service.py,test_view.py의 세 테스트 파일에서 공통적으로 사용할 mysql_engine을 database로 선언
def setup_function():
print("============setup_func============")
print("초기화")
database.execute(text("""
truncate users
"""))
new_users=[{
'id':1,
'name':'test1',
'email':'test1@naver.com',
'profile':'testuser1',
'hashed_password':hashed_password
},{
'id':2,
'name':'test2',
'email':'test2@naver.com',
'profile':'testuser2',
'hashed_password':hashed_password
}]
database.execute(text("""
insert into users (
id,
name,
email,
profile,
hashed_password
) values (
:id,
:name,
:email,
:profile,
:hashed_password
)
"""),new_users)
def teardown_function():
print("============teardown_func============")
print("초기화")
database.execute(text("""
truncate users
"""))
@pytest.fixture
def user_service():
return UserService(UserDao(database),config.test_config)
@pytest.fixture
def room_service():
return RoomService(RoomDao(database),config.test_config)
email_auth_info=user_service.get_email_auth_info(sample_email)
assert email_auth_info=={
'email':sample_email,
'auth_password':"1234",
'activated':0
}
*위처럼 fixture를 선언해 놓고 선언한 함수 이름을 test_get_email_auth_info의 인자로 넣으면 test_get_email_auth_info가 실행전 미리 선언한 함수의 결과값을 인자로 받는다.
...
#새로운 유저 가입 검증
def test_insert_user(user_dao):
#type이 기본 회원가입인 유저
new_user={
'name':'test4',
'email':'test4@naver.com',
'profile':'testuser4',
'password':'test_password',
'type':'image_us'
}
hashed_password=bcrypt.hashpw(new_user['password'].encode('utf-8'),bcrypt.gensalt())
new_user['hashed_password']=hashed_password
new_user_id=user_dao.insert_user(new_user)
user=get_user_info(new_user_id)
assert user=={
'id':new_user_id,
'name':new_user['name'],
'email':new_user['email'],
'profile':new_user['profile']
}
...
...
#새로운 유저를 생성
def test_create_new_user(user_service):
new_user={
'name':'test4',
'email':'test4@naver.com',
'profile':'testuser4',
'password':'test_password'
}
#새로운 유저를 만들고 정보를 확인
new_user_id=user_service.create_new_user(new_user)
new_user=get_user_info(new_user_id)
assert new_user=={
'id':new_user_id,
'name':new_user['name'],
'email':new_user['email'],
'profile':new_user['profile']
}
...
...
@pytest.fixture(scope='session')
def api():
app=create_app(test_config=config.test_config)
app.config['TEST']=True
api=app.test_client()
return api
...
#유저의 정보 불러오기
def test_get_user(api):
#존재하는 유저 정보 확인
user_id=1
resp=api.get(f"/user/{user_id}")
assert resp.status_code==200
resp_json=json.loads(resp.data.decode('utf-8'))
assert resp_json=={
'user_info':
{
'id':1,
'name':'test1',
'email':'test1@naver.com',
'profile':'testuser1'
}
}
#존재하지 않는 유저 정보 확인
user_id=100
resp=api.get(f"/user/{user_id}")
assert resp.status_code==404
...
pytest test_model.py -vv
pytest test_service.py -vv
pytest test_view.py -vv
*pytest -vv만 입력하면 모든 파일의 모든 test키워드가 붙은 함수가 실행된다.