2010-03-10 21 views
47

Tôi thích ý tưởng thử nghiệm đơn vị nhưng tôi gặp sự cố khi áp dụng nó cho lập trình trò chơi. Trò chơi có trạng thái cao và thường mã không tự chia thành các đơn vị riêng biệt. Theo kinh nghiệm của tôi, hầu hết các chức năng thay đổi trạng thái thay vì trả về các giá trị.Kiểm thử đơn vị có khả thi trong lập trình trò chơi không?

Hãy xem xét một hành động đơn giản như playerJump(height). Tôi rất muốn có một bộ kiểm tra kiểm tra nhiều trường hợp để đảm bảo rằng nhảy luôn hoạt động như mong đợi. Tuy nhiên, hàm này có thể sẽ không trả về giá trị nào và có tác dụng phụ là, player.velocity.y = -heightcheckCollisions(player). Tôi không thể nghĩ ra một bài kiểm tra đơn vị rõ ràng để xây dựng xung quanh điều này.

Thử nghiệm đơn vị có thực sự không khả thi trong các ứng dụng có trạng thái cao như trò chơi không? Là những lợi thế của thử nghiệm đơn vị tuyệt vời như vậy mà nó sẽ có giá trị trò chơi lập trình chức năng?


Cập nhật:

Games từ bên trong có một loạt các bài báo trong chiều sâu về việc sử dụng Test Driven Development trong các trò chơi. Tôi rất khuyến khích họ cho bất kỳ ai quan tâm đến chủ đề này. Dưới đây là bài viết đầu tiên:

http://gamesfromwithin.com/stepping-through-the-looking-glass-test-driven-game-development-part-1

+0

Đối với UnitTest ++, hãy truy cập github.com/unittest-cpp/unittest-cpp. Mọi thứ khác đã lỗi thời. – Markus

Trả lời

29

Thường mã không phá vỡ bản thân thành các đơn vị khác nhau.

Đó chỉ là thiết kế kém. Mã không tự biến thành bất kỳ thứ gì. Bạn, nhà thiết kế, phải áp đặt một cấu trúc trên mã để bạn có thể chứng minh rằng nó thực sự hoạt động.

Tuy nhiên, chức năng này sẽ có khả năng quay trở lại không có giá trị ...

Thì sao?

... và có tác dụng phụ là, player.velocity.y = -heightcheckCollisions(player).

Sau đó, kiểm tra điều đó.

Tôi không thể nghĩ ra một thử nghiệm đơn vị rõ ràng để xây dựng xung quanh điều này.

Tại sao không? Bạn vừa đưa ra một đặc điểm kỹ thuật tuyệt vời cho các kết quả của hàm.

Bạn có thể cần một vài đối tượng giả để thay thế Trình phát hoàn toàn bằng MockPlayer được đơn giản hóa dễ dàng hơn để kiểm tra.

Nhưng đặc điểm hoạt động của bạn là hoàn hảo. Chỉ cần kiểm tra những điều bạn mô tả.

+4

Ah tôi hiểu rồi. Tôi nghĩ rằng tôi đang giải thích "thử nghiệm đơn vị" quá theo nghĩa đen. Tôi đang tưởng tượng thử nghiệm các đầu vào và đầu ra của mỗi chức năng. Thay vào đó, kiểm tra có thể xác nhận các ràng buộc trên toàn bộ hệ thống sau khi một hàm được gọi. Cảm ơn, nó luôn luôn tốt đẹp để thoát khỏi tầm nhìn kênh lập trình của tôi :) – Kai

+0

@Kai: Vì thay đổi trạng thái của hệ thống là * tác dụng phụ * của hàm, bạn vẫn đang thực hiện thử nghiệm đơn vị vì hàm được kiểm tra riêng biệt. Nó rất dễ dàng để thử nghiệm với Mock Objects. Tôi không chắc chắn lý do tại sao bạn muốn yêu cầu kiểm tra đơn vị đó bằng cách nào đó bị giới hạn ở đầu vào và đầu ra của các chức năng thích hợp. –

+3

Một vấn đề tôi có với ý tưởng này là thử nghiệm có thể kết thúc như là phức tạp và dễ bị lỗi như các đơn vị đang được thử nghiệm. Lấy ví dụ thay đổi trạng thái dựa trên đánh dấu như vận tốc mà không có giá trị có thể cài đặt nào được thay đổi nhưng các giá trị có thể thay đổi sẽ thay đổi theo từng dấu tích. Người ta sẽ phải tạo ra một mô phỏng hành vi vận tốc để kiểm tra, thực thi lại mã vận tốc ban đầu một cách hiệu quả nhưng nếu nó không kiểm tra được, đó có phải là đơn vị bị lỗi hoặc thử nghiệm không? – user515655

13

Bài kiểm tra đơn vị có thể hữu ích cho nhiều thư viện cấp thấp mà bạn có thể sử dụng với mã trò chơi nhưng tôi nghiêm túc nghi ngờ rằng nó được sử dụng nhiều cho công cụ cấp cao hơn. Trò chơi thường là mô phỏng và dựa vào số lượng lớn trạng thái được chia sẻ mà không thể mô phỏng và thử nghiệm một cách có ý nghĩa một cách có ý nghĩa. Thường thì các chức năng trong trò chơi không trả về bất kỳ loại giá trị nào mà bạn có thể kiểm tra ngay lập tức mà thay vào đó hãy đặt một quá trình chuyển động cần hoàn thành tại một số điểm trong tương lai. Kiểm tra hành vi như vậy là đáng giá nhưng đòi hỏi một cách tiếp cận khác biệt đáng kể đối với ý tưởng thử nghiệm đơn vị thử nghiệm các đoạn mã trong sự cô lập.

+1

Đây là mô tả rõ ràng hơn về vấn đề tôi đã mô tả, cảm ơn. Nó có thể đáng xem nếu quá trình được thiết lập trong chuyển động đã thực sự kết thúc như mong đợi, nhưng nó có vẻ tốn nhiều thời gian hơn kiểm tra đầu vào và đầu ra chức năng đơn giản. – Kai

0

Kiểm tra đơn vị không quan tâm đến cách đơn vị của bạn "trạng thái" như thế nào. Bạn có một đoạn mã độc lập hơn hoặc ít hơn, và nếu vector đầu vào và đầu ra của nó là rất lớn thì việc thử nghiệm là khó khăn. Các vector này có được đặt dưới dạng các trạng thái trước và sau khi thực thi không thay đổi một chút về thử nghiệm hay không. Tuy nhiên, nếu bạn muốn cho chúng tôi biết rằng bạn không thể nghĩ ra một cách thích hợp để xác định các trường hợp thử nghiệm như trong các bài hướng dẫn/bài kiểm tra đơn vị có đầu óc đơn giản, tức là đối tượng thử nghiệm là "f (x) = y", sau đó có, tôi đồng ý, bạn sẽ có một thời gian khó khăn chứng minh rằng vài (x [100], y [99]) vectơ mà một con người mía đến với sản lượng bảo hiểm đầy đủ (numerics!). Cố gắng xây dựng các thuộc tính tích hợp và bất biến và đi thử nghiệm tự động.

0

Hãy xem PEX để tạo thử nghiệm đơn vị tự động. Nó sẽ tạo ra các bài kiểm tra đơn vị cho tất cả các biến thể đầu vào có thể, sẽ giúp bạn kiểm tra nhiều kết hợp có thể.

+1

Không chỉ là PEX .NET? Câu hỏi này không được gắn thẻ dưới dạng câu hỏi .NET. – Paddyslacker

16

Lập trình là lập trình. Bài kiểm tra đơn vị rất hữu ích cho bất kỳ loại ứng dụng nào vì chúng giúp bạn phát hiện và sửa lỗi (và thường quan trọng hơn, hồi quy vô tình được giới thiệu khi bạn mã refactor) ngay lập tức và hiệu quả. Có một số lĩnh vực hành vi cấp cao khó kiểm tra đơn vị, nhưng đó không thực sự là những bài kiểm tra đơn vị - chúng chủ yếu để kiểm tra các phương thức riêng lẻ hoặc các phần nhỏ của codebase thực hiện những gì chúng được cho là làm. Đối với các hành vi cấp cao hơn, bạn cần phải áp dụng các phương pháp thử nghiệm khác (kiểm tra hồi quy, ví dụ: cho ăn một chuỗi đầu vào cố định vào trò chơi và sau đó kiểm tra xem bạn có nhận được kết quả tương tự mọi lúc hay không. vị trí cố định trong suốt một cấp và kiểm tra xem chúng có tạo ra cùng một hình ảnh giống nhau (hoặc ít nhất là tương tự) không)

Ví dụ về PlayerJump của bạn là một trường hợp như vậy. Bạn có thể đơn vị hoặc hồi quy kiểm tra điều này bằng cách cô lập nó với đầu vào không đổi (lập trình đặt nhân vật người chơi tại một vị trí cố định trong một cảnh thử nghiệm đơn giản và kích hoạt sự kiện nhảy, sau đó kiểm tra xem va chạm của anh ta hoặc nơi an nghỉ cuối cùng là phù hợp. thư viện của các đối tượng khác nhau mà người chơi có thể nhảy "tại", bạn có thể bao gồm rất nhiều trường hợp kiểm tra (ví dụ: nhảy thành công trong khoảng cách của khoảng cách nhảy tối đa được quy định)

Ngoài ra, trò chơi yêu cầu Điều này sẽ tìm thấy những trường hợp kỳ lạ mà bạn đã không bao gồm với các bài kiểm tra tự động, nhưng quan trọng hơn nó sẽ trả lời một câu hỏi mà tự động kiểm tra sẽ không bao giờ trả lời: Liệu nó "cảm thấy" đúng Đây có phải là những bài kiểm tra chỉ một con người có thể thực hiện không.

+3

+1 Tâm trí bạn kiểm tra đơn vị trình kết xuất là không thể thực hiện được. Một số người sử dụng phương pháp pixar và chụp cùng một cảnh điều khiển từ cùng một góc với cùng một ánh sáng và bóng đổ và làm một hình ảnh so sánh – zebrabox

6

Trải nghiệm của tôi với đơn vị và tự động kiểm tra trong quá trình phát triển Crysis 2 có sẵn tại đây: http://yetanothergameprogrammingblog.blogspot.com/2010/06/aaa-automated-testing.html Hy vọng điều đó sẽ hữu ích.

Tóm tắt:

thử nghiệm tự động cải thiện sự ổn định phân phôi, tăng năng suất cho cả người sáng tạo nội dung và kỹ sư thử nghiệm tự động là một công cụ hiệu quả để cải thiện chất lượng mã và giảm nguy cơ của việc phải làm thêm giờ The Game nghiệp như tổng thể là phản động nói chung, thử nghiệm tự động đáp ứng một số đối số bất hợp lý chống lại Đừng gọi nó là thử nghiệm, gọi nó là cái gì khác, gần như bất cứ điều gì khác (Nhìn vào hành vi-Driven-Phát triển) Hãy linh hoạt, viết bài kiểm tra tốt là khó khăn và yêu cầu các kỹ năng không có sẵn trong ngành công nghiệp game

+0

Xin chào, chào mừng bạn đến với Stack Overflow! Liên kết tới giải pháp tiềm năng luôn được chào đón, nhưng hãy thêm ngữ cảnh xung quanh liên kết để người dùng đồng nghiệp của bạn sẽ có một số ý tưởng về nó là gì và tại sao nó lại ở đó. Luôn trích dẫn phần có liên quan nhất của một liên kết quan trọng. Hãy tưởng tượng rằng trang đó được chuyển sang máy chủ khác hoặc thay đổi liên kết trực tiếp - người dùng trong tương lai sẽ không thể hưởng lợi từ câu trả lời. Hãy xem [cách trả lời] (http://stackoverflow.com/questions/how-to-answer). – Jesse

0

Nhiều người lập trình trò chơi sử dụng Entity-component-system architecture.Họ làm điều đó bởi vì nó làm cho nó dễ dàng hơn để sửa đổi hành vi đối tượng trò chơi. Nhưng khi nó xảy ra, nó cũng giúp đơn vị kiểm tra mã của bạn dễ dàng hơn.