지난 포스트에서는 간단한 매소드만 구현되어 있는 최상위 클래스인 BaseField를 구현하고 테스트를 해보았다. 이번 포스트에서는 BaseField를 상속받는 문자열 타입의 StringField, 정수형 타입의 IntegerField, 날짜형 타입의 DatetimeField를 만들어보도록 하겠다.
1. 문자열 타입 객체
1-1. StringField 객체 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
# fields.py
"""
BaseField 밑에 이어서 작성
"""
class StringField(BaseField):
def __init__(self, maxlength=None, **kwargs):
super(StringField, self).__init__(str, **kwargs)
# 유효성검사 옵션값
self.__maxlength = maxlength
# Overriding: 유효성검사
def validate(self, value=None):
exists = value is not None
value = value if exists else self.getValue()
length = len(value) if exists else 0
# 유효성검사: 필수값
if bool(self.required) and not exists:
raise ValueError("This value was Required, but it is None.")
# 유효성검사: 최대길이
if bool(self.__maxlength) and exists and length > self.__maxlength:
raise ValueError("Expected value length %d, but %d." % ( self.__maxlength, length ))
|
cs |
1-2. StringField 객체 테스트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
# test.fields.py
"""
TestBaseField 밑에 이어서 작성
"""
from fields import StringField
class TestStringfield(object):
# 문자열 필드
field = StringField(required=True, maxlength=10)
def __init__(self):
print("Stringfield 테스트")
print("="*30)
for attrname in dir(self):
testcase = getattr(self, attrname)
if attrname.startswith("test") and callable(testcase):
print("=========", attrname, "========")
try:
testcase()
except Exception as e:
print("Error: "+str(e))
print("="*30)
def test_case_1(self):
print("문자열 필수값 오류 확인")
print("Input: None")
self.field.setValue(None)
print("Value: "+str(self.field.getValue()))
def test_case_2(self):
print("문자열 타입 오류 확인")
print("Input: 1234")
self.field.setValue(1234)
print("Value: "+str(self.field.getValue()))
def test_case_3(self):
print("문자열 최대길이 오류 확인")
print("Input: '1234567890#'")
self.field.setValue('1234567890#')
print("Value: "+str(self.field.getValue()))
def test_case_4(self):
print("문자열 정상")
print("Input: 'Hello!!'")
self.field.setValue("Hello!!")
print("Value: "+str(self.field.getValue()))
# 테스트 실행
TestStringfield()
|
cs |
1-3. StringField 객체 테스트 결과
2. 정수형 타입 객체
2-1. IntegerField 객체 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
# fields.py
"""
StringField 밑에 이어서 작성
"""
class IntegerField(BaseField):
def __init__(self, min=None, max=None, **kwargs):
super(IntegerField, self).__init__(int, **kwargs)
# 유효성검사 옵션값
self.__min = min
self.__max = max
# Overriding: 유효성검사
def validate(self, value=None):
exists = value is not None
value = value if exists else self.getValue()
# 유효성검사: 최솟값
if bool(self.__min) and exists and value < self.__min:
raise ValueError("Expected minimum %d, but %d." % ( self.__min, value ))
# 유효성검사: 최댓값
if bool(self.__max) and exists and value > self.__max:
raise ValueError("Expected maximum %d, but %d." % ( self.__max, value ))
|
cs |
2-2. IntegerField 객체 테스트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
# test.fields.py
"""
TestStringField 밑에 이어서 작성
"""
from fields import IntegerField
class TestIntegerField(object):
# 정수형 필드
field = IntegerField(required=True, min=10, max=100)
def __init__(self):
print("IntegerField 테스트")
print("="*30)
for attrname in dir(self):
testcase = getattr(self, attrname)
if attrname.startswith("test") and callable(testcase):
print("=========", attrname, "========")
try:
testcase()
except Exception as e:
print("Error: "+str(e))
print("="*30)
def test_case_1(self):
print("정수형 필수값 오류 확인")
print("Input: None")
self.field.setValue(None)
print("Value: "+str(self.field.getValue()))
def test_case_2(self):
print("정수형 타입 오류 확인")
print("Input: '100'")
self.field.setValue('100')
print("Value: "+str(self.field.getValue()))
def test_case_3(self):
print("정수형 최솟값 오류 확인")
print("Input: 3")
self.field.setValue(3)
print("Value: "+str(self.field.getValue()))
def test_case_4(self):
print("정수형 최댓값 오류 확인")
print("Input: 999")
self.field.setValue(999)
print("Value: "+str(self.field.getValue()))
def test_case_4(self):
print("정수형 정상")
print("Input: 100")
self.field.setValue(100)
print("Value: "+str(self.field.getValue()))
# 테스트 실행
TestIntegerField()
|
cs |
2-3. IntegerField 객체 테스트 결과
3. 날짜형 타입 객체
3-1. DatetimeField 객체 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
# fields.py
"""
IntegerField 밑에 이어서 작성
"""
from datetime import datetime, timedelta
class DatetimeField(BaseField):
def __init__(self, format="%Y-%m-%d %H:%M:%S", min=None, max=None, *args, **kwargs):
super(DatetimeField, self).__init__(datetime, *args, **kwargs)
self.__value = None
self.__format = format
self.__min = None
self.__max = None
# 제한시간 설정: 최소
if min is not None:
if min == 'now':
self.__min = datetime.now()
elif isinstance(min, str):
self.__min = datetime.strptime(min, format)
else:
self.__min = min
# 제한시간 설정: 최대
if max is not None:
if max == 'now':
self.__max = datetime.now()
elif isinstance(max, str):
self.__max = datetime.strptime(max, format)
else:
self.__max = max
# 값 설정
def setValue(self, value, format=None, validate=True):
self.__value = None
# 유효성검사: 문자열 포맷 확인
if isinstance(value, str):
value = datetime.strptime(value, format or self.__format)
if validate:
# 유효성검사
self.validate(value)
self.__value = value
# 값 반환, datetime
def getValue(self, format=None):
return self.__value
# Overriding: 유효성검사
def validate(self, value=None):
exists = value is not None
value = value if exists else self.getValue()
# 유효성검사: 타입체크
if exists and not isinstance(value, self.type):
raise TypeError("Expected data type '%s', but '%s'." %( self.type.__name__, value.__class__.__name__ ))
# 유효성검사: 필수값
if bool(self.required) and not exists:
raise ValueError("This value was Required, but it is None.")
# 유효성검사: 최소시간
if bool(self.__min) and exists:
# 최소시간 데이터 형변환
min = None
if isinstance(self.__min, timedelta):
min = datetime.now()+self.__min
else:
min = self.__min
if value < min:
raise ValueError("Expected datetime less than (%s), but %s." % ( min, value ))
# 유효성검사: 최대시간
if bool(self.__max) and exists:
# 최대시간 데이터 형변환
max = None
if isinstance(self.__max, timedelta):
max = datetime.now()+self.__max
else:
max = max
if value > max:
raise ValueError("Expected datetime greater than (%s), but %s." % ( max, value ))
|
cs |
3-2. DatetimeField 객체 테스트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
# test.fields.py
"""
TestIntegerField 밑에 이어서 작성
"""
from fields import DatetimeField
from datetime import datetime, timedelta
class TestDatetimeField(object):
# 날짜형 필드
field = DatetimeField(required=True, format="%Y-%m-%d %H:%M:%S", min='now', max=timedelta(hours=1))
def __init__(self):
print("DatetimeField 테스트")
print("="*30)
for attrname in dir(self):
testcase = getattr(self, attrname)
if attrname.startswith("test") and callable(testcase):
print("=========", attrname, "========")
try:
testcase()
except Exception as e:
print("Error: "+str(e))
print("="*30)
def test_case_1(self):
print("날짜형 필수값 오류 확인")
print("Input: None")
self.field.setValue(None)
print("Value: "+str(self.field.getValue()))
def test_case_2(self):
print("날짜형 포맷 오류 확인")
print("Input: '2021/01/19 23:59:59'")
self.field.setValue('2021/01/19 23:59:59')
print("Value: "+str(self.field.getValue()))
def test_case_3(self):
print("날짜형 타입 오류 확인")
print("Input: 1000")
self.field.setValue(1000)
print("Value: "+str(self.field.getValue()))
def test_case_4(self):
value = datetime.now() - timedelta(minutes=5)
print("날짜형 최소시간 오류 확인")
print("Input: %s (현재시간 - 5분)" %( value ))
self.field.setValue(value)
print("Value: "+str(self.field.getValue()))
def test_case_5(self):
value = datetime.now() + timedelta(hours=2)
print("날짜형 최댓값 오류 확인")
print("Input: %s (현재시간 + 2시간)" %( value ))
self.field.setValue(value)
print("Value: "+str(self.field.getValue()))
def test_case_6(self):
value = datetime.now() + timedelta(minutes=30)
print("날짜형 정상")
print("Input: %s (현재시간 + 30분)" %( value ))
self.field.setValue(value)
print("Value: "+str(self.field.getValue()))
# 테스트 실행
TestDatetimeField()
|
cs |
3-3. DatetimeField 객체 테스트 결과
마치며
- 이것으로 StringField, IntegerField, DatetimeField를 모두 구현해보았다. 문자열과 정수형은 딱히 어려운 부분이 없었는데, 날짜형은 계산과 데이터 형변환이 필요한 부분이 좀 있어서 복잡해지긴 했지만, 그래도 잘 돌아간다.
- 다음 포스트에서는 지금까지 만든 데이터 타입 객체들을 이용한 데이터 모델을 만들어 보도록 하겠다.
'Back-end > Python' 카테고리의 다른 글
[Python] Data Model 만들기 (3) - Data Model (0) | 2021.01.20 |
---|---|
[Python] Data Model 만들기 (1) - BaseField (0) | 2021.01.19 |
[Python] Flask & Socket.io를 이용한 채팅 (1) | 2020.08.03 |
[Tail] Python을 이용한 tail --follow 기능 구현 (1) | 2020.07.20 |
[GraphQL] 무작정 시작하기 (5) - Connection Field를 이용한 Pagination (0) | 2020.05.04 |
댓글