NỘI DUNG BÀI HỌC

✅ Hiểu tại sao xử lý lỗi là kỹ năng SỐNG CÒN để xây dựng kịch bản automation ổn định.
✅ Nắm vững và vận dụng thành thạo toàn bộ khối lệnh
try, except, else, và finally.
✅ Biết cách bắt và xử lý nhiều loại lỗi cụ thể (
Specific Exceptions) để kịch bản linh hoạt hơn.
✅ Chủ động tạo ra lỗi một cách có chủ đích bằng từ khóa
raise để kiểm soát luồng chương trình.
✅ Xây dựng được các hàm automation "an toàn" có khả năng tự xử lý các tình huống không mong muốn.


1. Tại sao phải xử lý lỗi? Kịch bản "giòn tan" vs. Kịch bản "bền bỉ"

Hãy tưởng tượng bạn đang viết một kịch bản automation để kiểm tra 100 test case.

  • Kịch bản "giòn tan" (Brittle Script): Chạy đến test case thứ 5, một pop-up quảng cáo bất ngờ xuất hiện làm script không tìm thấy nút "Thanh toán". Script báo lỗi đỏ lè và dừng lại ngay lập tức. Bạn mất trắng kết quả của 95 test case còn lại.

  • Kịch bản "bền bỉ" (Robust Script): Chạy đến test case thứ 5, kịch bản cũng không tìm thấy nút "Thanh toán". Nhưng thay vì dừng lại, nó được lập trình để:

    1. Thử (try) tìm nút.

    2. Phát hiện lỗi (except) NoSuchElementException.

    3. Bên trong except, nó kiểm tra xem có pop-up quảng cáo không. Nếu có, nó đóng pop-up đi.

    4. Thử tìm lại nút "Thanh toán" một lần nữa.

    5. Báo cáo test case thứ 5 là FAILED nhưng tiếp tục chạy 95 test case còn lại.

Xử lý lỗi (Exception Handling) chính là công cụ giúp chúng ta biến kịch bản từ "giòn tan" thành "bền bỉ".


2. Khối lệnh
try...except - Lưới an toàn của bạn

Đây là cấu trúc cơ bản nhất để "bẫy" lỗi, ngăn không cho chương trình bị dừng đột ngột.

  • try: Đặt đoạn code mà bạn dự đoán có khả năng gây ra lỗi vào trong khối này.

  • except: Nếu có lỗi xảy ra trong khối try, chương trình sẽ bỏ qua phần còn lại của try và nhảy ngay đến khối except để thực thi.


2.1 So sánh
try-except (Python) và try-catch (ngôn ngữ khác)

Nếu bạn đã từng lập trình với các ngôn ngữ như Java, C#, C++ hay JavaScript, bạn sẽ quen thuộc với cú pháp try-catch. Trong Python, cơ chế xử lý lỗi hoàn toàn tương tự về mặt chức năng, nhưng sử dụng từ khóa khác: try-except.

Về bản chất, chúng là một. Nếu bạn hiểu try-catch, bạn đã hiểu 90% về try-except. Chỉ cần nhớ rằng trong thế giới Python, chúng ta dùng except thay cho catch.

Bảng so sánh nhanh:

Tiêu chí Python (try-except) Ngôn ngữ khác (ví dụ: Java, C# - try-catch)
Từ khóa chính try, except, else, finally try, catch, finally
Bắt lỗi except ValueError as e: catch (ValueError e) { ... }
Bắt nhiều lỗi except (ValueError, TypeError): Thường dùng nhiều khối catch riêng biệt hoặc các cú pháp khác tùy ngôn ngữ.
Mục đích Hoàn toàn giống nhau: "bẫy" các lỗi xảy ra trong khối try để chương trình không bị dừng đột ngột. Hoàn toàn giống nhau: "bẫy" các lỗi xảy ra trong khối try để chương trình không bị dừng đột ngột.

 


2.2 Bắt một loại lỗi cụ thể

Việc chỉ định rõ loại lỗi bạn muốn bắt (ZeroDivisionError, ValueError, NoSuchElementException) là một thói quen rất tốt, giúp code rõ ràng và xử lý đúng vấn đề.

  • 🔹 Ví dụ trong cuộc sống: Một máy bán hàng tự động.

    • try: Bạn đưa tiền và chọn món.

    • except PaymentError: Nếu máy không nhận tiền, nó báo "Lỗi thanh toán".

    • except OutOfStockError: Nếu món hàng đã hết, nó báo "Sản phẩm tạm hết hàng".

    try:
        age_input = input("Vui lòng nhập tuổi của bạn: ")
        age = int(age_input)
        if age < 0:
            print("Tuổi không thể là số âm.")
        else:
            print(f"Bạn {age} tuổi.")
    except ValueError:
        # Lỗi này xảy ra khi int() không thể chuyển đổi chuỗi thành số (ví dụ: người dùng nhập "abc")
        print("Lỗi: Dữ liệu nhập vào không phải là một con số hợp lệ.")
     
  • 🔹 Ứng dụng trong Automation: Xử lý tình huống một element không tồn tại trên trang.

    from selenium.common.exceptions import NoSuchElementException
    
    # Giả sử `driver` là một đối tượng trình duyệt
    try:
        # Cố gắng tìm và click vào pop-up quảng cáo
        close_button = driver.find_element(By.ID, "close-popup-btn")
        close_button.click()
        print("Đã tìm thấy và đóng pop-up quảng cáo.")
    except NoSuchElementException:
        # Chỉ xử lý khi element không được tìm thấy
        print("Thông báo: Không có pop-up nào xuất hiện, tiếp tục các bước tiếp theo.")
    
     

✍️ Bài tập thực hành phần 2.2

  1. Tính toán an toàn: Viết chương trình chia 2 số a và b do người dùng nhập. Dùng try-except riêng biệt để bắt lỗi ValueError (nếu nhập chữ) và ZeroDivisionError (nếu chia cho 0) với các thông báo lỗi tương ứng.


2.3 Bắt nhiều loại lỗi cùng lúc

Bạn có thể bắt nhiều loại exception trong cùng một khối except bằng cách đặt chúng trong một tuple.

  • 🔹 Ví dụ trong cuộc sống: Bạn thử gọi điện cho một người bạn.

    • try: Bấm số và gọi.

    • except (NoSignalError, LowBatteryError): Nếu không có sóng hoặc hết pin, bạn đều không thể gọi được và sẽ thử lại sau.

    try:
        my_dict = {"name": "John"}
        key = input("Nhập key bạn muốn truy cập: ") # Ví dụ: 'age'
        print(my_dict[key])
    except (KeyError, IndexError) as e:
        # Bắt cả hai lỗi: truy cập key không tồn tại trong dict, hoặc chỉ số ngoài phạm vi trong list
        print(f"Lỗi truy cập dữ liệu: {e}")
    
    
     
  • 🔹 Ứng dụng trong Automation: Khi một hành động có thể thất bại vì nhiều lý do. Ví dụ, việc click một nút có thể thất bại vì không tìm thấy nó, hoặc tìm thấy nhưng bị che khuất, hoặc element đã bị "lỗi thời" (stale).

    from selenium.common.exceptions import NoSuchElementException, ElementClickInterceptedException, StaleElementReferenceException
    
    try:
        button = driver.find_element(By.CSS_SELECTOR, "#submit-btn")
        button.click()
    except (NoSuchElementException, ElementClickInterceptedException, StaleElementReferenceException) as e:
        print(f"Không thể click vào nút submit. Lý do: {type(e).__name__}")
        # type(e).__name__ sẽ cho bạn biết tên của lớp Exception, ví dụ: 'NoSuchElementException'
    
    


    ✍️
    Bài tập thực hành phần 2.3

    1. Đọc file linh hoạt: Viết code để mở và đọc một file có tên do người dùng nhập. Dùng một khối except duy nhất để bắt cả hai lỗi FileNotFoundError (file không tồn tại) và PermissionError (không có quyền đọc file).

3. Hoàn thiện quy trình với elsefinally

  • else: Chỉ được thực thi khi khối try chạy thành côngkhông gây ra lỗi nào.

  • finally: Luôn luôn được thực thi, bất kể có lỗi hay không. Đây là nơi hoàn hảo cho các hành động "dọn dẹp".

  • 🔹 Ví dụ trong cuộc sống: Giao dịch tại ATM.

    1. try: Yêu cầu rút 1,000,000đ.

    2. except InsufficientFundsError: Nếu không đủ tiền, máy báo lỗi.

    3. else: Nếu rút tiền thành công, máy in biên lai.

    4. finally: Bất kể thành công hay thất bại, máy luôn trả lại thẻ cho bạn.

    try:
        f = open("config.ini", "r")
    except FileNotFoundError:
        print("Lỗi: Không tìm thấy file config.ini.")
    else:
        # Chỉ chạy nếu file được mở thành công
        print("Đọc file config thành công.")
        # ... xử lý nội dung file ...
        f.close() # Đóng file trong else cũng là một cách
    finally:
        # Luôn chạy, dù có lỗi hay không
        print("--- Kết thúc quá trình xử lý cấu hình ---")
    
    
     
  • 🔹 Ứng dụng trong Automation: Đây là cấu trúc VÀNG để đảm bảo sự ổn định và sạch sẽ của test case.

    try:
        print("Bắt đầu test case: Thêm sản phẩm vào giỏ hàng")
        # 1. Tìm sản phẩm
        # 2. Click nút "Thêm vào giỏ"
        # 3. Chờ và xác nhận thông báo thành công xuất hiện
        assert "Thêm vào giỏ hàng thành công" in driver.page_source
    except Exception as e:
        # Nếu bất kỳ bước nào ở trên thất bại
        print(f"❌ TEST FAILED: {e}")
    else:
        # Chỉ chạy nếu tất cả các bước trong try đều thành công
        print("✅ TEST PASSED: Sản phẩm đã được thêm vào giỏ hàng thành công.")
    finally:
        # Luôn luôn thực hiện để dọn dẹp
        print("Đang chụp ảnh màn hình kết quả...")
        driver.save_screenshot("add_to_cart_result.png")
        # driver.quit() # Đóng trình duyệt sau khi test xong
    #Selenium – tìm element
    try:
        btn = driver.find_element(By.ID, "login")
        btn.click()
    except NoSuchElementException:
        print("❌ Không tìm thấy nút login")
    finally:
        driver.quit()
    
    #Data-driven test – đọc test data từ file
    try:
        with open("testdata.csv", "r") as f:
            print(f.readlines())
    except FileNotFoundError:
        print("❌ Không tìm thấy file test data")
    

✍️ Bài tập thực hành phần 3

  1. Xác nhận và Dọn dẹp: Mở rộng bài tập tính toán an toàn ở phần 2.2. Dùng khối else để in ra kết quả phép chia chỉ khi không có lỗi. Dùng khối finally để luôn luôn in ra "Chương trình tính toán kết thúc."


4. Chủ động báo lỗi với
raise

Đôi khi, bạn muốn chương trình của mình tự tạo ra một lỗi khi một điều kiện logic nào đó không được đáp ứng. raise cho phép bạn làm điều đó.

  • 🔹 Ví dụ trong cuộc sống: Bạn đi khám bệnh, bác sĩ (hàm) kiểm tra nhiệt độ (dữ liệu) của bạn. Nếu nhiệt độ trên 38°C (điều kiện không hợp lệ), bác sĩ sẽ "raise" một cảnh báo "Bệnh nhân bị sốt!" để y tá xử lý.

    def set_age(age):
        if not isinstance(age, int):
            raise TypeError("Tuổi phải là một số nguyên.")
        if age < 0:
            raise ValueError("Tuổi không thể là một số âm.")
        print(f"Tuổi đã được đặt là: {age}")
    
    try:
        set_age(-5)
    except (TypeError, ValueError) as e:
        print(f"Lỗi khi đặt tuổi: {e}")
     
  • 🔹 Ứng dụng trong Automation: Khi bạn viết một hàm tiện ích, và muốn nó báo hiệu một cách rõ ràng khi gặp phải tình huống không thể xử lý.

    def get_element_text(driver, locator):
        """Hàm này lấy text của element, nhưng sẽ báo lỗi nếu element rỗng."""
        try:
            element = driver.find_element(*locator) # *locator dùng để giải nén tuple (By.ID, "some_id")
            text = element.text.strip()
            if text == "":
                # Element tồn tại nhưng không có text, đây là một lỗi logic
                raise ValueError(f"Element tại {locator} không chứa text.")
            return text
        except NoSuchElementException:
            # Ném lại lỗi để báo cho nơi gọi hàm biết rằng element không tồn tại
            raise NoSuchElementException(f"Không tìm thấy element với locator: {locator}")
    
    # Cách sử dụng
    try:
        welcome_message = get_element_text(driver, (By.ID, "welcome-msg"))
        print(f"Thông điệp chào mừng: {welcome_message}")
    except (NoSuchElementException, ValueError) as e:
        print(f"Không thể lấy thông điệp chào mừng. Lý do: {e}")


5.
Mini Quiz 🎯

  1. Trong Python dùng từ khóa nào để bẫy lỗi? 

  2. finally có chạy khi trong try bị lỗi không? 

  3. Khi nào else được chạy? 

  4. Điểm khác biệt chính giữa try–catch (Java/C#) và try–except (Python)?

  5. Output của code sau?

    try:
        print(5/0)
    except ZeroDivisionError:
        print("Lỗi chia cho 0")
    finally:
        print("Kết thúc")
    


6. Bài tập tổng hợp cuối buổi

Bài 1: Nhập số

Viết chương trình yêu cầu người dùng nhập số.

  • Nếu nhập đúng → in bình phương.

  • Nếu nhập sai → in "Sai định dạng".

Bài 2: Máy tính an toàn

Viết hàm safe_divide(a, b) chia 2 số.

  • Nếu b = 0 → trả về "Không thể chia cho 0".

  • Ngược lại → trả về kết quả.

Bài 3: File

Đọc file data.txt.

  • Nếu file tồn tại → in nội dung.

  • Nếu không → in "File không tồn tại".

  • Luôn in "Kết thúc chương trình".

Bài 4: Automation

  • Giả lập tìm element "submit".

  • Nếu không tìm thấy → in "Không tìm thấy element".

  • Luôn in "Đóng trình duyệt".

 

👉  Đây là một hàm tiện ích cực kỳ phổ biến trong các framework automation thực tế, giúp bạn kết hợp tất cả kiến thức đã học để tạo ra một kịch bản mạnh mẽ và dễ gỡ lỗi.

Teacher

Teacher

Hà Lan

QA Automation

With over 5 years of experience in web, API, and mobile test automation, built strong expertise in designing and maintaining automation frameworks across various domains and international projects. Committed to mentoring and knowledge sharing, I provide practical guidance and proven techniques to help aspiring testers develop their skills and succeed in the automation field.

Cộng đồng Automation Testing Việt Nam:

🌱 Telegram Automation Testing:   Cộng đồng Automation Testing
🌱 
Facebook Group Automation: Cộng đồng Automation Testing Việt Nam
🌱 
Facebook Fanpage: Cộng đồng Automation Testing Việt Nam - Selenium
🌱 Telegram
Manual Testing:   Cộng đồng Manual Testing
🌱 
Facebook Group Manual: Cộng đồng Manual Testing Việt Nam

Chia sẻ khóa học lên trang

Bạn có thể đăng khóa học của chính bạn lên trang Anh Tester để kiếm tiền

Danh sách bài học