Xin chào ! Nếu đây là lần đầu tiên bạn đến với diễn đàn, xin vui lòng danh ra một phút bấm vào đây để đăng kí và tham gia thảo luận cùng VnPro.

Announcement

Collapse
No announcement yet.

Xây dựng Python Unit Test

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Xây dựng Python Unit Test

    Cài đặt thư viện pytest:

    Nhấn tổ hợp phím Win +R để vào cmd: gõ py –m pip install pytest
    Hoặc py –m pip install pytest --user


    Khi thấy dòng chữ Successfully installed là chúng ta đã cài đặt thành công thư viện pytest

    Viết class Student, contructor và các phương thức hoạt động của class Student và Subject:

    Đầu tiên chúng ta sẽ tạo contructor bằng def __init__ để khai báo các thuộc tính cho class Student. Các tham số đầu vào của hàm này gồm 2 tham số self và name. Self là tham số bắt buộc phải có của mỗi khi tạo contructor hoặc phương thức hoạt động của class. Name là tên của học viên. Email ở phần này không cần đề cập đến nên không có tham số email.
    Code:
    [FONT=Calibri][FONT=Times New Roman]class Student:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def __init__(self, name):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]self.name = name[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]self.email = None[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]self.subjects = [][/FONT][/FONT]
    [FONT=Times New Roman]self.grades = [][/FONT]
    Tiếp theo chúng ta sẽ mở một file python mới để tạo class Subject liên kết với class Student, cũng tạo contructor có 1 thuộc tính là name, sau khi xong nhớ lưu file và đặt tên là subject.py
    Code:
    [FONT=Calibri][FONT=Times New Roman]class Subject:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def __init__(self, name):[/FONT][/FONT]
    [FONT=Times New Roman]self.name = name[/FONT]
    Chúng ta sẽ trở về file viết class Student và import file subject.py
    Code:
    import subject
    Sau đó trong class Student chúng ta viết một hàm mới add_subject(), công việc cần thực hiện bên trong hàm này là kiểm tra xem subject có khác None hay không, nếu khác None ta sẽ đến với điều kiện if tiếp theo là kiểm tra nếu subject không trong class Student thì sẽ gán giá trị của subject vào thuộc tính subjects của class Student
    Code:
    [FONT=Calibri][FONT=Times New Roman]def add_subject(self, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]if subject:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]if subject not in self.subjects:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]self.subjects.append(subject)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]return True[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]else:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]return False[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]else:[/FONT][/FONT]
    [FONT=Times New Roman]return False[/FONT]
    Và hàm set_grade() để ghi điểm vào trong môn học, chúng ta sẽ kiểm tra tương tự như hàm ở trên là xem các tham số subject, grade có khác None hay không và đặc biệt ở đây là grade có thể =0 nên cần viết thêm vế sau “grade is int(0)”.Nếu 2 tham số trên khác None rồi thì đi đến kiểm tra grade có vượt quá khoảng 1-10 hay không, nếu có thì xuất lỗi ra, không vượt khoảng 1-10 thì gán vào thuộc tính grade của class Student.
    Code:
    [FONT=Calibri][FONT=Times New Roman]def set_grade(self, subject, grade):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]if (subject and grade) or (subject and grade is int(0)):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]if subject in self.subjects:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]if grade < 1 or grade > 10:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]raise ValueError('grade out of bound', grade)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]else:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]self.grades.append((subject, grade))[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]return True[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]else:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]raise ValueError('no subject or grade', subject)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]else:[/FONT][/FONT]
    [FONT=Times New Roman]return False[/FONT]
    Phương thức cuối cùng get_grades_for_subject() dùng để lấy tất cả các điểm của môn học nào đó, việc đầu tiên là kiểm tra subjects có khác None hay không, khác None thì chúng ta sẽ tạo một list grades để chứa tất cả các điểm, list grades này sẽ là giá trị trả về khi hàm này được gọi.
    Code:
    [FONT=Calibri][FONT=Times New Roman]def get_grades_for_subject(self, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]if subject:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]grades = [][/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]for grade in self.grades:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]if grade[0] is subject:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]grades.append(grade[1])[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]else:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]return False[/FONT][/FONT]
    [FONT=Times New Roman]return grades[/FONT]


    Viết file conftest.py:

    Mở file python mới và import thư viện pytest
    Code:
    import pytest
    Tiếp theo là khai báo các fixture của pytest bằng @pytest.fixture, fixture này giống như function, nó sẽ chạy trước test function và được dùng để đưa dữ liệu vào các test. Thay vì phải chạy các phần code giống nhau mỗi khi test, chúng ta có thể khai báo trước fixture function, nó sẽ được chạy và trả về dữ liệu trước khi thực thi mỗi test. Để fixture có thể dùng trong nhiều file test thì phải định nghĩa những fixture function trong file conftest.py.
    Yield trong pytest giống như return, del là xóa. Dưới đây là những giá trị sẽ được khởi tạo và được sử dụng khi test function gọi chúng.
    Code:
    [FONT=Calibri][FONT=Times New Roman]@pytest.fixture[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def student():[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]from student import Student[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]stud = Student('Luka Zauber')[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]yield stud[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]del stud[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]@pytest.fixture[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def subject():[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]from subject import Subject[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]s = Subject('Unit Testing 101')[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]yield s[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]del s[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]@pytest.fixture[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def subjects():[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]from subject import Subject[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]s = [Subject('Unit Testing 101'), Subject('CS500')][/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]yield s[/FONT][/FONT]
    [FONT=Times New Roman]del s[/FONT]
    Sau khi viết xong chúng ta lưu dưới tên conftest.py, lưu ý tên phải này bắt buộc phải đặt như vậy để pytest nhận biết file này chứa các fixture


    Viết file test theo con đường thuận lợi:

    Phần này chúng ta sẽ viết các chức năng liệt kê các trường hợp mà các giá trị mong muốn khi đi vào code sẽ như thế nào. Ở đây chúng ta sẽ sử dụng @pytest.mark.usefixture(‘tên fixture’) để pytest chạy các fixture, lấy các giá trị của fixture đưa vào trong các test
    Code:
    [FONT=Calibri][FONT=Times New Roman]import pytest[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]@pytest.mark.usefixtures('student', 'subject')[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]class TestHappyPath:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def test_add_subject_to_student(self, student, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]assert student.add_subject(subject) is True[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]def test_add_grade_to_subject(self, student, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.add_subject(subject)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]assert student.set_grade(subject, 8) is True[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]def test_get_subject_grade(self, student, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.add_subject(subject)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.set_grade(subject, 8)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.set_grade(subject, 9)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]assert student.get_grades_for_subject(subject) == [8, 9][/FONT][/FONT]
    Chúng ta sẽ kiểm tra các các giá trị khởi tạo trên khi đi vào code có thành công hay không,bao gồm các chức năng thêm môn học, thêm điểm cho môn học và lấy các điểm trong môn học.
    Sau khi viết xong thì lưu file tên test_grades_happypath.py, sau đó vào cmd gõ: pytest test_grades_happypath.py sẽ chạy file test


    Viết file test theo con đường sẽ gây lỗi:

    Phần cuối cùng sẽ là viết các chức năng để kiểm tra khi đưa những giá trị không mong muốn (gây lỗi).
    Code:
    [FONT=Calibri][FONT=Times New Roman]import pytest[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]@pytest.mark.usefixtures('student', 'subject')[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]class TestErrorPathSubject:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]#Thêm tên môn học để trống (None)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def test_add_empty_subject_to_student(self, student, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]assert student.add_subject(None) is False[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]#Thêm môn học đã có[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def test_add_existing_subject_to_student(self, student, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.add_subject(subject)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]assert student.add_subject(subject) is False[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]@pytest.mark.usefixtures('student', 'subject')[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]class TestErrorPathAddGrade:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]#Thêm điểm cao hơn khoảng cho phép[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def test_add_higher_grade_to_subject(self, student, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.add_subject(subject)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]with pytest.raises(ValueError):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.set_grade(subject, 11)[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]#Thêm điểm thấp hơn khoảng cho phép[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def test_add_lower_grade_to_subject(self, student, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.add_subject(subject)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]with pytest.raises(ValueError):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.set_grade(subject, -1)[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]#Thêm điểm 0 vào môn học[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def test_add_zero_grade_to_subject(self, student, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.add_subject(subject)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]with pytest.raises(ValueError):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.set_grade(subject, 0)[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]@pytest.mark.usefixtures('student', 'subject', 'subjects')[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]class TestErrorPathGetGrade:[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]#Thêm điểm vào môn học không có[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def test_get_none_subject_grade(self, student, subject):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.add_subject(subject)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.set_grade(subject, 8)[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]assert student.get_grades_for_subject(None) is False[/FONT][/FONT]
    
    [FONT=Calibri][FONT=Times New Roman]#Lấy điểm không có trong môn học[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]def test_get_missing_subject_grade(self, student, subjects):[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.add_subject(subjects[0])[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.add_subject(subjects[1])[/FONT][/FONT]
    [FONT=Calibri][FONT=Times New Roman]student.set_grade(subjects[0], 8)[/FONT][/FONT]
    [FONT=Times New Roman]assert student.get_grades_for_subject(subjects[1]) == [][/FONT]
    Sau khi viết xong lưu file tên là test_grades_errorpath.py sau đó vào cmd gõ: pytest test_grades_errorpath.py


    Hoàn thành.

    Thank you.
    Nguồn : VNPRO
Working...
X