2009-11-30 27 views
18

Tôi đã có một dự án lớn được viết bằng PHP và Javascript. Vấn đề là nó trở nên quá lớn và không thể duy trì được rằng việc thay đổi một số phần nhỏ của mã sẽ khó chịu và có thể phá vỡ rất nhiều phần khác.Làm cách nào để triển khai khung kiểm tra trong dự án cũ

Tôi thực sự rất xấu khi thử nghiệm mã của riêng mình (thực tế, những người khác chỉ ra điều này hàng ngày), điều này thậm chí còn khó khăn hơn trong việc duy trì dự án. Bản thân dự án không phải là phức tạp hay phức tạp, nó còn là cách mà nó được xây dựng khiến nó trở nên phức tạp: chúng tôi không có các quy tắc hoặc danh sách được xác định trước để làm theo khi thực hiện thử nghiệm của chúng tôi. Điều này thường dẫn đến nhiều lỗi và khách hàng không hài lòng.

Chúng tôi bắt đầu thảo luận điều này tại văn phòng và nảy ra ý tưởng bắt đầu sử dụng phát triển thử nghiệm thay vì phát triển như địa ngục và có thể kiểm tra sau (hầu như luôn luôn sửa lỗi).

Sau nền đó, những điều tôi cần giúp đỡ như sau:

  1. Làm thế nào để thực hiện một khuôn khổ kiểm tra vào một dự án đã tồn tại? (3 năm trong việc thực hiện và tính )

  2. Loại khung nào có để thử nghiệm? Tôi nghĩ tôi sẽ cần một khung cho Javascript và một cho PHP.

  3. Cách tiếp cận tốt nhất để kiểm tra giao diện người dùng đồ họa là gì?

Tôi chưa bao giờ sử dụng Kiểm tra đơn vị trước đây vì vậy đây thực sự là lãnh thổ chưa được tìm hiểu đối với tôi.

+5

+1 Đây là một câu hỏi hay. Trong thực tế, tôi nghĩ rằng có một khoảng cách thị trường cho một cuốn sách về chủ đề giới thiệu các bài kiểm tra đơn vị cho một dự án di sản. –

+1

Rất nhiều người trên SO dường như đang đề xuất cuốn sách này: http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052 – yoosiba

Trả lời

6

G'day,

Edit: Tôi vừa mới có một cái nhìn nhanh chóng thông qua các chương đầu tiên của "The Art of Unit Testing" mà cũng có sẵn như là a free PDF tại book's website. Nó sẽ cung cấp cho bạn một cái nhìn tổng quan về những gì bạn đang cố gắng làm với một bài kiểm tra đơn vị.

Tôi giả sử bạn sẽ sử dụng một khung loại xUnit. Vài suy nghĩ cao cấp ban đầu là:

  1. Edit: đảm bảo rằng tất cả mọi người là một sự thống nhất như thế nào là một bài kiểm tra đơn vị tốt. Tôi muốn đề nghị sử dụng chương tổng quan ở trên như là một điểm khởi đầu tốt và nếu cần thiết lấy nó từ đó. Hãy tưởng tượng có người chạy rất nhiệt tình để tạo ra rất nhiều bài kiểm tra đơn vị trong khi có một sự hiểu biết khác nhau về những gì một thử nghiệm đơn vị "tốt". Bạn sẽ thấy khó khăn trong tương lai khi 25% bài kiểm tra đơn vị của bạn không hữu ích, lặp lại, đáng tin cậy, v.v.
  2. thêm các bài kiểm tra để bao gồm các đoạn mã nhỏ tại một thời điểm. Tức là, đừng tạo một tác vụ đơn nguyên khối để thêm các bài kiểm tra cho cơ sở mã hiện có.
  3. sửa đổi bất kỳ quy trình hiện có nào để đảm bảo rằng các thử nghiệm mới được thêm vào cho bất kỳ mã mới nào được viết. Làm cho nó trở thành một phần của quá trình xem xét mã mà các bài kiểm tra đơn vị phải được cung cấp cho chức năng mới.
  4. mở rộng mọi quy trình sửa lỗi hiện có để đảm bảo rằng các thử nghiệm mới được tạo để hiển thị sự hiện diện và chứng minh sự vắng mặt của lỗi. N.B. Đừng quên khôi phục lại bản sửa lỗi ứng viên của bạn để giới thiệu lỗi một lần nữa để xác minh rằng đó chỉ là bản vá duy nhất đã khắc phục sự cố và nó không được cố định bởi sự kết hợp của các yếu tố.
  5. Chỉnh sửa: khi bạn bắt đầu xây dựng số lượng thử nghiệm của mình, bắt đầu chạy chúng dưới dạng kiểm tra hồi quy hàng đêm để kiểm tra xem không có gì bị phá vỡ bởi chức năng mới.
  6. thực hiện một hoạt động thành công là tất cả các tiêu chí kiểm tra và mục nhập hiện có cho quá trình xem xét của một lỗi ứng cử viên.
  7. Chỉnh sửa: bắt đầu lưu danh mục các loại thử nghiệm, ví dụ: đoạn mã thử nghiệm, để giúp tạo các thử nghiệm mới dễ dàng hơn. Không có ý nghĩa trong việc phát minh lại bánh xe mọi lúc. (Các) bài kiểm tra đơn vị được viết để kiểm tra việc mở một tệp trong một phần của cơ sở mã là/sẽ tương tự với (các) bài kiểm tra đơn vị được viết để kiểm tra mã mở một tệp khác trong một phần khác của cơ sở mã . Phân loại các danh mục này để dễ tìm.
  8. Chỉnh sửa: nơi bạn chỉ sửa đổi một vài phương pháp cho lớp hiện có, tạo bộ kiểm tra để giữ toàn bộ các bài kiểm tra cho lớp. Sau đó, chỉ thêm các thử nghiệm riêng lẻ cho các phương thức bạn đang sửa đổi cho bộ thử nghiệm này. Điều này sử dụng thuật ngữ xUnit như tôi bây giờ giả sử bạn sẽ sử dụng một khung công tác xUnit như PHPUnit.
  9. sử dụng quy ước chuẩn để đặt tên cho các thử nghiệm và các thử nghiệm của bạn, ví dụ: testSuite_classA sau đó sẽ chứa các bài kiểm tra riêng lẻ như test__test_function. Ví dụ: test_fopen_bad_name và test_fopen_bad_perms, v.v. Điều này giúp giảm thiểu tiếng ồn khi di chuyển xung quanh cơ sở mã và xem xét các bài kiểm tra của người khác. Nó cũng có lợi ích khi giúp đỡ mọi người khi họ đến để đặt tên cho các bài kiểm tra của họ ngay từ đầu bằng cách giải phóng tâm trí của họ để làm việc trên những thứ thú vị hơn như bản thân các bài kiểm tra.
  10. Chỉnh sửa: tôi sẽ không sử dụng TDD ở giai đoạn này. Theo định nghĩa, TDD sẽ cần tất cả các bài kiểm tra trình bày trước khi các thay đổi được đặt ra, do đó bạn sẽ có các bài kiểm tra không thành công trên toàn bộ địa điểm khi bạn thêm các testSuites mới để bao gồm các lớp mà bạn đang làm việc. Thay vào đó, hãy thêm testSuite mới và sau đó thêm các bài kiểm tra cá nhân theo yêu cầu để bạn không nhận được nhiều tiếng ồn xảy ra trong kết quả kiểm tra của bạn cho các bài kiểm tra không thành công. Và, như Yishai chỉ ra, việc bổ sung nhiệm vụ học TDD vào thời điểm này sẽ thực sự làm chậm bạn. Đặt TDD học tập như là một nhiệm vụ được thực hiện khi bạn có một số thời gian rảnh rỗi. Nó không phải là khó khăn.
  11. như một hệ quả của việc này, bạn sẽ cần một công cụ để theo dõi các lớp hiện có, nơi testSuite tồn tại nhưng các bài kiểm tra chưa được viết để bao gồm các hàm thành viên khác trong lớp. Bằng cách này bạn có thể theo dõi vị trí kiểm tra của bạn có lỗ hổng. Tôi đang nói ở một mức độ cao ở đây, nơi bạn có thể tạo ra một danh sách các lớp và các hàm thành viên cụ thể mà không có các bài kiểm tra hiện đang tồn tại. Quy ước đặt tên chuẩn cho các bài kiểm tra và testSuites sẽ giúp bạn rất nhiều ở đây.

Tôi sẽ thêm nhiều điểm hơn khi nghĩ về chúng.

HTH

+2

Tôi có nên đi viết các trường hợp kiểm tra cho các lớp học hoàn chỉnh cùng một lúc hay chỉ các phương pháp? Hãy nhớ rằng, tôi mới cho doanh nghiệp thử nghiệm đơn vị này :) – Skoog

+0

@Skoog, vừa thêm một liên kết đến phần giới thiệu tuyệt vời để kiểm tra đơn vị. –

+1

Tôi cảm ơn bạn thay mặt cho toàn bộ nhóm của chúng tôi. Rất nhiều thứ bạn đã cung cấp. – Skoog

0

Việc triển khai khung trong hầu hết các trường hợp là một nhiệm vụ phức tạp vì bạn bắt đầu xây dựng lại mã cũ của mình bằng một số phần khung vững chắc mới. Những phần cũ đó phải bắt đầu giao tiếp với khung công tác. Các bộ phận cũ phải nhận được một số callbacks và returnstates, các bộ phận cũ sau đó bằng cách nào đó chỉ ra rằng người dùng và trong thực tế, bạn đột nhiên có 2 hệ thống để kiểm tra.

Nếu bạn nói rằng bạn tự ứng dụng không phức tạp nhưng nó đã trở thành do thiếu kiểm tra, nó có thể là một lựa chọn tốt hơn để xây dựng lại ứng dụng. Đặt một số khung công tác phổ biến như Zend vào thử nghiệm, thu thập các yêu cầu của bạn, tìm hiểu xem khuôn khổ thử nghiệm có phù hợp với yêu cầu và quyết định xem nó có hữu ích để bắt đầu lại hay không.

Tôi không chắc lắm về thử nghiệm đơn vị, nhưng NetBeans có bộ thử nghiệm đơn vị tích hợp sẵn.

3

Từ góc độ quy hoạch, tôi nghĩ rằng bạn có ba lựa chọn cơ bản:

  1. mất một chu kỳ để retrofit mã với đơn vị kiểm tra
  2. ñònh một phần của đội bóng để retrofit mã với đơn vị kiểm tra
  3. giới thiệu các bài kiểm tra đơn vị dần dần khi bạn làm việc trên mã

Cách tiếp cận đầu tiên có thể kéo dài lâu hơn bạn dự đoán và năng suất hiển thị của bạn sẽ bị ảnh hưởng.Nếu bạn sử dụng nó, bạn sẽ cần phải nhận được mua từ tất cả các bên liên quan của bạn. Tuy nhiên, bạn có thể sử dụng nó để bắt đầu quá trình.

Vấn đề với cách tiếp cận thứ hai là bạn tạo sự phân biệt giữa các lập trình viên và các nhà văn thử nghiệm. Các lập trình viên sẽ không cảm thấy bất kỳ quyền sở hữu nào đối với việc bảo trì kiểm tra. Tôi nghĩ cách tiếp cận này đáng để tránh.

Cách tiếp cận thứ ba là phương pháp hữu cơ nhất và giúp bạn phát triển theo hướng thử nghiệm từ khi bắt đầu. Nó có thể mất một thời gian cho một cơ thể hữu ích của các bài kiểm tra đơn vị để tích lũy. Tốc độ tích lũy thử nghiệm chậm có thể thực sự là một lợi thế ở chỗ nó mang lại cho bạn thời gian để có được bài kiểm tra viết tốt.

Tất cả những điều được xem xét, tôi nghĩ rằng tôi muốn lựa chọn một nước rút khiêm tốn theo tinh thần của phương pháp 1, tiếp theo là một cam kết để tiếp cận 3.

Đối với các nguyên tắc chung về kiểm tra đơn vị tôi khuyên bạn nên cuốn sách xUnit Test Patterns: Refactoring Test Code bởi Gerard Meszaros.

+0

Tôi nghĩ đây sẽ là cách tiếp cận có khả năng nhất với chương trình phụ trợ của tôi mã. Tôi không biết liệu chúng ta có thể dành toàn bộ chạy nước rút để trang bị thêm không. Nhưng tôi chắc chắn khi chúng tôi làm việc với mỗi lớp, chúng tôi có thể viết các trường hợp kiểm tra cho mỗi lớp khi chúng tôi đi. – Skoog

2

Tôi đã sử dụng PHPUnit với kết quả tốt. PHPUnit, giống như các dự án khác có nguồn gốc từ JUnit, yêu cầu mã được kiểm thử phải được tổ chức thành các lớp. Nếu dự án của bạn không hướng đối tượng, thì bạn sẽ cần bắt đầu tái cấu trúc mã phi thủ tục thành các hàm và các hàm vào các lớp.

Tôi không đích thân sử dụng khung JavaScript, mặc dù tôi sẽ hình ảnh rằng các khung này cũng sẽ yêu cầu mã của bạn phải được cấu trúc thành (ít nhất) các hàm có thể gọi nếu không phải đối tượng đầy đủ.

Để thử nghiệm các ứng dụng GUI, bạn có thể hưởng lợi từ việc sử dụng Selenium, mặc dù danh sách kiểm tra được viết bởi một lập trình viên có bản năng QA tốt có thể hoạt động tốt. Tôi đã thấy rằng việc sử dụng MediaWiki hoặc công cụ Wiki yêu thích của bạn là một nơi tốt để lưu trữ danh sách kiểm tra và tài liệu dự án có liên quan.

+0

Vì nó xảy ra 70-80% là dựa trên lớp và phần còn lại vẫn là thủ tục. Vẫn làm việc chăm chỉ để có được 20% còn lại vào lớp học. – Skoog

+0

+1 PHPUnit. Tôi đã nghe báo cáo hỗn hợp về Selenium vì nó có xu hướng khuyến khích các xét nghiệm giòn. Mặc dù vậy, tôi không thể đề xuất một khung kiểm thử JS xUnit-y hơn. Nếu JS được tạo ra, kiểu GWT, thì có một xUnit cho điều đó. –

0

Nếu mã thực sự lộn xộn, có thể sẽ rất khó để thực hiện bất kỳ thử nghiệm đơn vị nào. Chỉ các thành phần được thiết kế vừa đủ và được thiết kế vừa đủ có thể được kiểm tra dễ dàng. Tuy nhiên, thử nghiệm chức năng có thể dễ dàng hơn nhiều trong việc thực hiện trong trường hợp của bạn. Tôi khuyên bạn nên xem Selenium. Với khung công tác này, bạn sẽ có thể kiểm tra GUI và chương trình phụ trợ cùng một lúc. Tuy nhiên, hầu hết có thể, nó sẽ không giúp bạn nắm bắt các lỗi cũng như bạn có thể với thử nghiệm đơn vị.

+0

Tôi sẽ nói khoảng một nửa số lỗi trong GUI chính nó, vì vậy Selenium có lẽ sẽ là một lựa chọn thực sự tốt ở đây. Tôi sẽ kiểm tra xem có ra ngoài không. Cảm ơn. – Skoog

6

Bạn sẽ nhận được bản sao Working Effectively with Legacy Code. Điều này sẽ cung cấp cho bạn hướng dẫn tốt về cách giới thiệu các bài kiểm tra vào mã không được viết để kiểm tra.

TDD là rất tốt, nhưng bạn cần bắt đầu bằng việc đặt mã hiện có đang được kiểm tra để đảm bảo rằng những thay đổi bạn thực hiện không thay đổi hành vi bắt buộc hiện tại trong khi giới thiệu thay đổi. Tuy nhiên, việc giới thiệu TDD bây giờ sẽ làm chậm bạn rất nhiều trước khi bạn quay trở lại, bởi vì kiểm tra trang bị thêm, thậm chí chỉ trong khu vực bạn đang thay đổi, sẽ trở nên phức tạp trước khi nó trở nên đơn giản.

+0

@Yishai, điểm tốt về hiệu ứng tiềm năng của việc giới thiệu muộn TDD. Tôi nghĩ rằng nó có thể được thêm vào cho mã hoàn toàn mới mặc dù người ta đã biết TDD rồi. Học TDD, khung xUnit và các bài kiểm tra đơn vị cơ bản cùng một lúc là ** không ** hoạt động tốt! –

0

Có lẽ danh sách này sẽ giúp bạn và bạn tình của bạn để tái cấu trúc tất cả mọi thứ:

  1. Sử dụng UML, thiết kế và xử lý ngoại lệ (http://en.wikipedia.org/wiki/Unified_Modeling_Language)
  2. Sử dụng BPMS, để thiết kế công việc dòng chảy của bạn, do đó bạn sẽ không đấu tranh (http://en.wikipedia.org/wiki/Business_process_management)
  3. Nhận danh sách các khung công tác php cũng hỗ trợ các chương trình phụ trợ javascript (ví dụ: Zend với jQuery)
  4. So sánh các khung này và thực hiện khung công tác phù hợp nhất với desgin dự án của bạn và cấu trúc mã hóa đã sử dụng trước
  5. Bạn nên chưa xem xét sử dụng những thứ như ezComponents và Dtrace để gỡ lỗi và thử nghiệm
  6. Đừng sợ những thay đổi;)
5

Chỉ cần để thêm vào các câu trả lời tuyệt vời khác, tôi đồng ý rằng đi từ 0% đến 100% mức độ phù hợp trong một lần là không thực tế - nhưng bạn nên chắc chắn thêm các bài kiểm tra đơn vị mỗi khi bạn sửa lỗi.

Bạn nói rằng có khá nhiều lỗi và khách hàng không hài lòng - tôi rất tích cực về việc kết hợp TDD chặt chẽ vào quá trình sửa lỗi, dễ dàng hơn nhiều so với triển khai tổng thể. Sau khi tất cả, nếu có thực sự là một lỗi có mà cần phải được cố định, sau đó tạo ra một bài kiểm tra đó tái tạo nó phục vụ mục đích khác nhau:

  • Đó là khả năng là một trường hợp thử nghiệm tối thiểu để chứng minh rằng có thực sự là một vấn đề
  • Với sự tự tin rằng bài kiểm tra (hiện đang thất bại) nêu bật vấn đề được báo cáo, bạn sẽ biết chắc chắn nếu các thay đổi của bạn đã sửa đổi nó
  • Nó sẽ mãi mãi đứng như một bài kiểm tra hồi quy sẽ ngăn vấn đề này lặp lại trong tương lai.

Giới thiệu các bài kiểm tra cho dự án hiện tại rất khó và có thể là một quá trình lâu dài, nhưng thực hiện chúng cùng một lúc như sửa lỗi là một thời điểm lý tưởng để làm như vậy (song song với giới thiệu bài kiểm tra dần dần) "cảm giác) rằng nó sẽ là một sự xấu hổ không để có cơ hội đó và làm cho nước chanh từ báo cáo lỗi của bạn. :-)

+0

Tôi đã đến với các điều khoản với nó là một quá trình lâu dài. Tôi chuẩn bị. Điều tôi quan tâm nhất là, tôi bắt đầu từ đâu? Làm cách nào để tiếp tục? Nhưng những thứ bạn mang lại, tôi hiểu. Tôi nghĩ rằng điều này sẽ làm việc thực sự tốt cho chúng tôi. Tôi chỉ cần đọc về chủ đề của TTD và thử nghiệm Đơn vị. Bạn sẽ có một số tài nguyên tốt cho người mới bắt đầu trong lĩnh vực này? – Skoog

0

Để kiểm tra GUI, bạn có thể muốn xem Selenium (như Ignas R đã chỉ ra) HOẶC bạn cũng có thể xem công cụ này: STIQ.

Chúc bạn may mắn!

0

Trong một số trường hợp, thử nghiệm tự động có thể không phải là một ý tưởng hay, đặc biệt khi cơ sở mã bị bẩn và PHP trộn lẫn hành vi của nó với Javascript. Có thể tốt hơn để bắt đầu với một danh sách kiểm tra đơn giản (với các liên kết, để làm cho nó nhanh hơn) của các xét nghiệm cần được thực hiện (thủ công) về điều trước mỗi lần giao hàng.

Khi mã hóa trong mỏ 3 năm tuổi, hãy tự bảo vệ mình tốt hơn với nhiều lần kiểm tra lỗi. 15 phút dành cho việc viết thông báo lỗi thích hợp cho từng trường hợp sẽ không bị mất.

Sử dụng phương pháp cầu nối: cầu hàm dài gấp nếp() với lệnh gọi hàm fnew() là một trình bao quanh một số lớp sạch, gọi cả hai lần và fnew và so sánh kết quả, sự khác biệt nhật ký, ném mã vào sản xuất và chờ đợi cho cá của bạn. Khi làm điều này, luôn luôn sử dụng một chu kỳ để tái cấu trúc, một chu trình KHÁC để thay đổi kết quả (thậm chí không sửa lỗi trong hành vi cũ, chỉ cần kết nối nó).

0

Tôi đồng ý với KOHb, Selen là phải!

Cũng có một cái nhìn tại PHPure,

phần mềm của họ ghi lại các đầu vào và đầu ra từ một trang web php làm việc, và sau đó tự động viết thử nghiệm phpunit cho các chức năng mà không truy cập vào các nguồn bên ngoài (db, file vv ..) .

Đó không phải là giải pháp 100%, nhưng đó là một khởi đầu tuyệt vời

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