2016-03-25 22 views
5

Tôi đang nhập unit testing của một số tập lệnh shell legacy.Thử nghiệm đơn vị Shell Script: Cách tạo mô hình chương trình tiện ích phức tạp

Trong kịch bản thế giới thực thường được sử dụng để gọi chương trình tiện ích như find, tar, cpio, grep, sed, rsync, date và như vậy với một số dòng lệnh khá phức tạp có chứa rất nhiều các tùy chọn. Đôi khi các biểu thức chính quy hoặc các mẫu ký tự đại diện được xây dựng và sử dụng.

An ví dụ: Tập lệnh shell thường được gọi bởi cron trong khoảng thời gian đều có nhiệm vụ phản chiếu một số cây thư mục khổng lồ từ máy này sang máy khác bằng tiện ích rsync. Một số loại tập tin và thư mục cần được loại trừ khỏi quá trình mirroring:

#!/usr/bin/env bash 
    ... 
    function mirror() { 
     ... 
     COMMAND="rsync -aH$VERBOSE$DRY $PROGRESS $DELETE $OTHER_OPTIONS \ 
        $EXCLUDE_OPTIONS $SOURCE_HOST:$DIRECTORY $TARGET" 
     ... 
     if eval $COMMAND 
     then ... 
     else ... 
     fi 
     ... 
    } 
    ... 

Như Michael Feathers viết trong cuốn sách nổi tiếng của ông Working Effectively with Legacy Code, một thử nghiệm đơn vị tốt chạy rất nhanh và không chạm vào mạng đó, File- hoặc mở bất kỳ cơ sở dữ liệu nào.

Theo lời khuyên của Michael Feathers, kỹ thuật sử dụng tại đây là: dependency injection. Đối tượng thay thế ở đây là chương trình tiện ích rsync.

ý tưởng đầu tiên của tôi: Trong vỏ khuôn khổ kiểm tra kịch bản của tôi (tôi sử dụng bats) Tôi thao tác $PATH trong một cách mà một mockuprsync được tìm thấy thay vì thực rsync tiện ích. Đối tượng mockup này có thể kiểm tra các tham số và tùy chọn dòng lệnh được cung cấp. Tương tự với các tiện ích khác được sử dụng trong phần này của script under test.

Trải nghiệm quá khứ của tôi với các vấn đề thực sự trong lĩnh vực này thường là các lỗi do ký tự đặc biệt trong tên tệp hoặc thư mục, sự cố với trích dẫn hoặc mã hóa, thiếu khóa ssh, quyền sai và vân vân. Những loại lỗi này sẽ thoát khỏi kỹ thuật kiểm thử đơn vị này. (Tôi biết: đối với một số trong những vấn đề này kiểm tra đơn vị chỉ đơn giản là không chữa bệnh).

Một nhược điểm nữa là viết một mockup cho một tiện ích phức tạp như rsync hoặc find là dễ bị lỗi và một nhiệm vụ kỹ thuật tẻ nhạt của riêng nó.

Tôi tin rằng tình huống được mô tả ở trên là đủ chung để những người khác có thể gặp phải sự cố tương tự. Ai đã có một số ý tưởng thông minh và muốn chia sẻ chúng ở đây với tôi?

+3

Sau khi kiểm tra đơn vị, bạn cần kiểm tra hệ thống. Có thể xây dựng một mạng thử nghiệm đơn giản với mỗi tệp có vấn đề, thư mục, khóa bị thiếu, v.v. – tripleee

+1

Sử dụng 'tee' nội tuyến với kịch bản thế giới thực để gọi câu trả lời lệnh, sau đó sử dụng các tệp đó để phát lại trong kịch bản được kiểm tra , có lẽ với một tập lệnh ghi nhật ký các đối số nhận được và gửi một cách mù quáng câu trả lời soạn trước. –

+0

@Keith Tyler: Đó là một ý tưởng thực sự gọn gàng: Rõ ràng kỹ thuật này yêu cầu một số loại thử nghiệm hệ thống được viết trước đó (nhưng khi bắt đầu fiddle trên một kịch bản cũ, viết ít nhất một số kiểm tra như vậy trước khi bắt đầu refactor kịch bản là anyway một tốt ý kiến). Theo dõi gợi ý này. – pefu

Trả lời

1

Cargill của tình thế khó khăn:

"Bất kỳ vấn đề thiết kế có thể được giải quyết bằng cách thêm một mức độ thêm về mình, trừ trường hợp quá nhiều cấp độ của mình"

Tại sao lệnh hệ thống giả? Sau khi tất cả nếu bạn đang lập trình Bash, hệ thống là mục tiêu mục tiêu của bạn và bạn nên đánh giá kịch bản của bạn bằng cách sử dụng hệ thống.

Kiểm tra đơn vị, như tên cho thấy, sẽ cung cấp cho bạn sự tự tin trong một phần đơn nhất của hệ thống bạn đang thiết kế. Vì vậy, bạn sẽ phải xác định đơn vị của bạn trong trường hợp tập lệnh bash là gì.Một chức năng? Tệp tập lệnh? Một lệnh?

đưa cho bạn muốn xác định đơn vị như một hàm sau đó tôi sẽ đề nghị viết một danh sách các lỗi nổi tiếng như bạn liệt kê ở trên:

  • Ký tự đặc biệt trong tập tin hoặc thư mục tên
  • Vấn đề với trích dẫn hoặc mã hóa
  • Thiếu các khóa ssh
  • Quyền hạn và v.v.

Và viết trường hợp thử nghiệm cho nó. Và cố gắng không đi chệch khỏi các lệnh hệ thống, vì chúng là tách rời một phần của hệ thống bạn đang phân phối.

0

Bạn có thể mockup bất kỳ lệnh sử dụng một chức năng, như thế này:

function rsync() { 
    # mock things here if necessary 
} 

Sau đó, xuất khẩu chức năng và chạy unittest:

export -f rsync 
unittest 
Các vấn đề liên quan