2011-08-26 37 views
36

Tôi hiện đủ ngu ngốc để cố gắng duy trì hai căn cứ mã song song cho ứng dụng máy tính để bàn Python, sử dụng PyGObject introspection cho GTK 3 và một sử dụng PyGTK cho GTK 2. Tôi làm việc chủ yếu trên nhánh PyGObject và sau đó tôi thay đổi cổng đến chi nhánh PyGTK. Do tất cả các khác biệt nhỏ giữa các triển khai này, tôi thường bỏ qua mọi thứ và gây ra sự cố mà tôi bỏ lỡ và vô tình phát hành, chỉ để bị người dùng bắt.Cách được khuyến nghị để bỏ qua các ứng dụng GUI của Python là gì?

Tôi đang cố gắng tìm ra cách tốt để thiết kế một số unittests, tốt nhất là phù hợp để chạy trên cả hai cơ sở mã. Nó không phải là một chương trình quá phức tạp, (đó là về cơ bản là một công cụ quản lý thư viện, hãy tưởng tượng như iTunes):

- Main Window 
    |- Toolbar with some buttons (add/edit/remove items, configure the program) 
    | 
    |- VPaned 
    |--- Top HPaned 
    |------ ListView (listing values by which a library of items can be filtered) 
    |------ ListView (listing the contents of the library 
    |--- Bottom HPaned 
    |------ Image (displaying cover art for the currently selected item in the library) 
    |------ TextView (displaying formatted text describing the currently selected item) 
- Edit dialog 
- Configuration dialog 
- About dialog 

Tôi đã cố gắng để xem từ các mô hình tách càng nhiều càng tốt. Mỗi mục trong số đó được thực hiện trong lớp riêng của nó (tốt, trong các lớp kế thừa từ các lớp GTK được liệt kê). ListViews được kết hợp với các lớp khác kế thừa từ ListStores. Bản thân thư viện được xử lý bởi một lớp khác. Tuy nhiên, có những tương tác giữa các vật dụng cần được kiểm tra. Ví dụ: nếu người dùng chọn một mục cụ thể trong chế độ xem bộ lọc, lọc thư viện và sau đó chọn một mục từ kết quả được lọc, thì chế độ xem văn bản phải hiển thị thông tin cho mục nhập thư viện chính xác. iters giữa TreeModelFilter và ListStore gốc, v.v.

Vì vậy, tôi hỏi, cách được khuyến nghị để viết thử nghiệm đơn vị mạnh mẽ cho ứng dụng GUI như thế nào? Tôi đã thấy rằng có một số thư viện cho điều này, nhưng những người chính cho pygtk đã không được cập nhật trong nhiều năm và do đó họ gần như chắc chắn sẽ thất bại với PyGObject introspection. Có lẽ tôi không đủ sáng tạo để tìm ra cách tốt để làm điều đó bằng cách sử dụng mô-đun unittest của Python, vì vậy tôi mở để đề xuất.

+0

Và trước khi có ai hỏi: pygtk không hỗ trợ GTK 3, nhưng tôi thấy rằng sự hỗ trợ cho sự mâu thuẫn pygobject của GTK 2 là quá không đầy đủ để phụ thuộc vào. –

+1

Đối với tôi, cách tốt nhất để tránh hồi quy khi sử dụng GUI là thực hiện các kiểm tra thủ công. Unittest thực sự tốt để thử nghiệm các chức năng làm việc (ví dụ như MVC) nhưng tôi không biết làm thế nào bạn có thể đối phó với gui ... – ykatchou

+0

Đây là những gì tôi đã làm nhưng tôi dường như không giỏi lắm, vì mọi bản phát hành tôi đều nhớ một vài thứ. –

Trả lời

4

Bạn có chắc chắn muốn đơn vị kiểm tra GUI không? Ví dụ phức tạp của bạn liên quan đến hơn 1 đơn vị và do đó là một thử nghiệm tích hợp.

Nếu bạn thực sự muốn thử nghiệm đơn vị, bạn sẽ có thể khởi tạo một lớp duy nhất cung cấp mocks hoặc sơ đồ cho các phụ thuộc của nó, sau đó gọi các phương thức trên nó như khung công tác GUI chẳng hạn. người dùng nhấp vào. Điều này có thể tẻ nhạt và bạn phải biết chính xác cách mà khung công tác GUI gửi đầu vào của người dùng tới các lớp của bạn.

Lời khuyên của tôi là đưa nhiều nội dung hơn vào các mô hình. Đối với ví dụ của bạn, bạn có thể tạo ra một FilterManager mà tóm tắt tất cả các công cụ lọc/chọn/hiển thị đằng sau một phương pháp duy nhất. Sau đó, đơn vị kiểm tra nó.

+0

Ah, có lẽ tôi đã có điều khoản của tôi sai sau đó (nó đã được gần 10 năm kể từ khi tôi đã học/sử dụng bất kỳ điều này). Nếu tôi có thể ngây thơ hỏi, thì, là thử nghiệm tích hợp được xác định rõ ràng hoặc có thể thiết kế như kiểm tra đơn vị? Tuy nhiên, tôi nghĩ rằng rất nhiều nó có thể được đơn vị thử nghiệm theo cách tôi đã viết nó, bằng cách sử dụng phương pháp được đề cập trong một bình luận về câu hỏi của tôi. –

+1

Vâng khái niệm cốt lõi của thử nghiệm đơn vị là để kiểm tra một đơn vị duy nhất tại một thời điểm, để giữ cho các bài kiểm tra hoàn thành, đơn giản, nhanh chóng và có thể xác định chính xác thất bại. Đôi khi điều này là khó khăn, đặc biệt là đối với GUI. Bạn có thể sử dụng một số mô-đun không nhất quán của Python cho các bài kiểm tra không đơn vị, nhưng bạn cũng mất một số lợi ích, và tôi sẽ không gọi nó là thử nghiệm đơn vị nữa. –

+1

Đây không phải là câu trả lời thực sự ... Rõ ràng là anh ấy muốn thử nghiệm tích hợp với PyGTK, vì vậy hãy chỉ cho anh ta đúng hướng thay vì sửa thuật ngữ. – schlamar

2

Trong gắn bó với đề tài mà Jürgen là đúng ở chỗ tôi không quan tâm đến việc đơn vị thử nghiệm, nhưng thực sự quan tâm đến việc thử nghiệm tích hợp, tôi cũng phát hiện khuôn khổ này từ freedesktop.org: http://ldtp.freedesktop.org/wiki/

Nó cho phép tự động hóa một loạt các bài kiểm tra cho các ứng dụng GUI hỗ trợ khả năng truy cập (bao gồm GTK, Qt, Swing, v.v.).

5

Có một cách tuyệt vời để kiểm tra các chức năng và tiện ích của PyGTK trực tiếp, mà không phải trải qua các khung kiểm tra chấp nhận/chức năng/tích hợp mà có thể đi vào quên lãng. Tôi đã tìm hiểu về điều này trong this post, điều này khá tự giải thích. Nhưng ý tưởng cơ bản là bạn coi các tiện ích của mình là các hàm/lớp và bạn có thể kiểm tra chúng trực tiếp.Nếu bạn cần xử lý các cuộc gọi lại và như vậy, có một mẹo nhỏ gọn mà tôi sẽ tái tạo tại đây:

import time 
import gtk 

# Stolen from Kiwi 
def refresh_gui(delay=0): 
    while gtk.events_pending(): 
     gtk.main_iteration_do(block=False) 
    time.sleep(delay) 

Như đã đề cập trong bài đăng trên blog, mã này là LGPL. Nếu không, khi bạn nghĩ về nó, miễn là bạn không show() cửa sổ hoặc tiện ích con, bạn có thể kiểm tra tất cả những gì bạn muốn và họ nên cư xử như thể họ là thực bởi vì, theo một cách nào đó, họ đang có. Chúng không được hiển thị.

Tất nhiên, bạn cần tự mô phỏng tương tác trên các nút và các tiện ích tương tác bằng cách gọi clicked() trên một nút. Xem lại Ali Afshar's excellent post about unit testing in PyGTK.

0

Bạn có thể sử dụng một bộ đệm khung X11:

Xvfb :119 -screen 0 1024x768x16 & 
export DISPLAY=:119 
... run your tests 

Hãy chắc chắn, không nhập gtk.main(), vì điều này sẽ chờ đợi cho chuột hoặc bàn phím đầu vào. Bạn có thể sử dụng mẫu này để cho phép gtk xử lý tất cả các sự kiện:

def refresh_gui(): 
    while gtk.events_pending(): 
     gtk.main_iteration_do(block=False) 

AFAIK bạn không thể thấy ứng dụng của mình, nhưng bạn có thể kiểm tra các cuộc gọi lại.

Các vấn đề liên quan