2009-08-27 19 views
78

Chúng tôi có một hệ thống có một số tập lệnh bash chạy bên cạnh mã Java. Vì chúng tôi đang cố gắng kiểm tra mọi thứ có thể có khả năng Break, và những tập lệnh bash đó có thể bị phá vỡ, chúng tôi muốn kiểm tra chúng.Kiểm tra đơn vị bash script

Vấn đề là rất khó để kiểm tra các tập lệnh bash.

Có cách nào hay cách hay nhất để kiểm tra tập lệnh bash? Hoặc chúng ta nên bỏ bằng cách sử dụng kịch bản bash và tìm kiếm các giải pháp thay thế có thể kiểm tra?

+0

cũng xem: http://stackoverflow.com/questions/1315624/bash-and-test-driven-development –

+0

bản sao có thể có của [Kiểm tra đơn vị cho tập lệnh shell] (http://stackoverflow.com/questions/971945/unit-testing-for-shell-scripts) – user

+0

Tổng quan về các công cụ hiện có: https://medium.com/wemake-services/testing-bash-applications-85512e7fe2de – sobolevn

Trả lời

22

tôi đã câu trả lời sau đây từ một nhóm thảo luận:

nó có thể phải nhập khẩu (bao gồm, bất cứ điều gì) một thủ tục (hàm, bất kỳ tên nào được đặt tên) từ tệp bên ngoài . Đó là chìa khóa để viết một kịch bản thử nghiệm: bạn chia tay kịch bản của bạn vào thủ tục độc lập mà sau đó có thể được nhập khẩu vào cả kịch bản của bạn chạy và kiểm tra kịch bản của bạn, và sau đó bạn có chạy của bạn kịch bản đơn giản càng tốt .

Phương pháp này giống như tiêm phụ thuộc cho tập lệnh và âm thanh hợp lý. Tránh sử dụng các tập lệnh bash và sử dụng nhiều ngôn ngữ có thể kiểm tra và ít bị che khuất hơn.

+3

Tôi không chắc liệu tôi có nên bỏ phiếu lên hay xuống, một tay chia nhỏ hơn là tốt, nhưng tôi cần một khung không phải là tập hợp các kịch bản tùy chỉnh – mpapis

+4

Khi nói đến thử nghiệm, imho, mô đun là tốt . – nimcap

+7

Trong khi không có gì sai với bash (tôi đã viết nhiều, nhiều kịch bản), nó là một ngôn ngữ khó để làm chủ. Quy tắc chung của tôi là nếu một tập lệnh đủ lớn để cần kiểm tra, có lẽ bạn nên chuyển sang ngôn ngữ kịch bản có thể dễ dàng kiểm tra. – Doug

36

Có thực sự là unit testing framework for shell scripts. Tôi đã không sử dụng nó bản thân mình, nhưng nó có thể là giá trị kiểm tra ra.

câu hỏi tương tự đã được hỏi trước:

+2

Tôi có thể khẳng định (chơi chữ có chủ ý) mà shunit2 (phiên bản 2.1 .6) là một chút bị hỏng cho đến nay. Xác nhậnNull và assertNotNull không hoạt động, ngay cả khi bạn cấp chúng cho các giá trị trực tiếp. assertEquals hoạt động tốt, nhưng tôi nghĩ tôi sẽ phải tự mình cuộn. – labyrinth

+0

@ mê cung, bạn có chắc chắn vấn đề không phải là một trường hợp này: https://github.com/kward/shunit2/issues/53 "Làm thế nào để sử dụng assertNull một cách chính xác?"? –

+0

@Victor Chắc chắn là tôi đã không đủ cẩn thận với dấu ngoặc kép của tôi. Tôi sẽ sớm quay trở lại vai trò mà hệ thống kiểm tra đơn vị shunit2 hoặc một số hệ thống thử nghiệm sẽ rất hữu ích. Tôi sẽ thử lại lần nữa. – labyrinth

-4

tôi đã tìm thấy nó khó để biện minh sử dụng bash cho các kịch bản lớn hơn khi Python có lợi thế lớn như vậy:

  • Thử/Ngoại trừ việc cho phép viết các kịch bản mạnh mẽ hơn với khả năng hoàn tác các thay đổi trong trường hợp xảy ra lỗi.
  • Bạn không phải sử dụng cú pháp không rõ ràng như 'if [ x"$foo" = x"$bar"]; then ...' dễ bị lỗi.
  • Phân tích cú pháp các tùy chọn và đối số dễ dàng bằng mô-đun getopt (và thậm chí còn có một mô-đun dễ dàng hơn để phân tích cú pháp đối số, nhưng tên đã thoát khỏi tôi).
  • Python cho phép bạn làm việc với các danh sách/dicts và các đối tượng thay vì chuỗi cơ bản và mảng.
  • Truy cập vào các công cụ ngôn ngữ thích hợp như regex, cơ sở dữ liệu (chắc chắn bạn có thể đưa mọi thứ vào lệnh mysql trong bash, nhưng đó không phải là cách tốt nhất để viết mã).
  • Không cần phải lo lắng về việc sử dụng đúng mẫu của $* hoặc "$*" hay "[email protected]" hoặc $1 hoặc "$1", khoảng trống trong tên tập tin không phải là một vấn đề, vv, vv, vv

Bây giờ tôi chỉ sử dụng bash cho đơn giản nhất của tập lệnh.

+3

Không phủ nhận thực tế là Python có lợi thế nhưng điểm thứ hai của bạn không được đặt rất tốt. So sánh tương tự có thể đã được thực hiện như 'if [[$ foo = $ bar]]; sau đó ... '. Điều này vẫn không tốt hơn những gì python cung cấp, nhưng nó tốt hơn những gì bạn trình bày. –

+8

Một số hệ thống (được nhúng cho ví dụ.) Không có sẵn python và bạn không thể/không muốn cài đặt thêm nội dung. –

+2

Cá nhân tôi yêu bash, nhưng đồng ý rằng nó có thể là một chút thử nghiệm. Bạn thường phải chủ động hơn nhiều trong khi trong Python bạn có thể giải quyết lỗi * sau * chúng đã xuất hiện. Tuy nhiên, bash không có 'trap' (để dọn dẹp/hoàn tác trong trường hợp lỗi) cũng như regex (tức là' [[$ 1 = ~^[1-3] {3} $]] '). Tôi khá chắc chắn cú pháp tối nghĩa mà bạn đã sử dụng là tham chiếu đến các lần triển khai cũ của 'test', chứ không phải bash. Bash là một công cụ tuyệt vời để giao tiếp với các công cụ dòng lệnh hiện có ... Thường là một đường ống đơn lẻ để 'awk' hoặc' grep' dễ dàng hơn nhiều so với phương thức Python. – Six

6

Tại sao bạn nói rằng thật khó để kiểm tra các tập lệnh bash?

Có gì sai với giấy gói thử nghiệm như:

#!/bin/bash 
set -e 
errors=0 
results=$($script_under_test $args<<ENDTSTDATA 
# inputs 
# go 
# here 
# 
ENDTSTDATA 
) 
[ "$?" -ne 0 ] || { 
    echo "Test returned error code $?" 2>&1 
    let errors+=1 
    } 

echo "$results" | grep -q $expected1 || { 
     echo "Test Failed. Expected $expected1" 
     let errors+=1 
} 
# and so on, et cetera, ad infinitum, ad nauseum 
[ "$errors" -gt 0 ] && { 
     echo "There were $errors errors found" 
     exit 1 
} 
+4

Đầu tiên, các tập lệnh bash không thể đọc được. Thứ hai, kỳ vọng phức tạp như kiểm tra xem tệp khóa có được tạo bằng PID của tập lệnh bash đã tạo ra nó không. – nimcap

+7

Quan trọng hơn, thật khó để kiểm tra các kịch bản shell vì chúng thường có một số lượng lớn các hiệu ứng phụ và sử dụng các tài nguyên hệ thống như hệ thống tập tin, mạng, vv Lý tưởng, các bài kiểm tra đơn vị có tác dụng phụ miễn phí và không phụ thuộc vào tài nguyên hệ thống. – jayhendren

16

TAP -compliant thử nghiệm Bash: Bash Automated Testing System

+11

Nó đáng để tiết lộ TAP là gì và tại sao lại nên quan tâm, nếu không nó chỉ là một bản sao vô nghĩa –

+0

@ om-nom-nom: Tôi đã liên kết nó với trang TAP ngay bây giờ. –

+5

Vì không có ai khác nói rằng không thể trả lời: TAP = Kiểm tra giao thức bất kỳ –

6

Epoxy là một khuôn khổ kiểm tra Bash tôi được thiết kế chủ yếu để thử nghiệm các phần mềm khác, nhưng tôi sử dụng nó để kiểm tra module bash là tốt, bao gồm itselfCarton.

Ưu điểm chính là chi phí mã hóa tương đối thấp, lồng xác nhận không giới hạn và lựa chọn linh hoạt các xác nhận để xác minh.

Tôi đã thực hiện presentation so sánh nó với BeakerLib - một khung được một số người sử dụng tại Red Hat.

1

Tôi khá thích shell2junit, một tiện ích để tạo đầu ra giống như JUnit từ các kiểm tra tập lệnh Bash. Điều này rất hữu ích vì báo cáo được tạo ra sau đó có thể được đọc bởi các hệ thống tích hợp liên tục, chẳng hạn như các trình cắm thêm JUnit cho Jenkins và Bamboo.

Trong khi shell2junit không cung cấp khung kịch bản lệnh Bash toàn diện như shunit2, nó cho phép bạn có báo cáo tốt đẹp về kết quả kiểm tra.

2

Hãy thử bashtest. Đó là cách đơn giản để kiểm tra kịch bản của bạn. Ví dụ: bạn có do-some-work.sh thay đổi một số tệp cấu hình. Ví dụ: thêm dòng mới PASSWORD = 'XXXXX' vào tệp cấu hình /etc/my.cfg.

Bạn viết các lệnh bash từng dòng và sau đó kiểm tra đầu ra.

Install:

pip3 install bashtest 

Tạo bài kiểm tra là một chỉ viết lệnh bash.

file test-do-some-work.bashtest:

# run the script 
$ ./do-some-work.sh > /dev/null 

# testing that the line "PASSWORD = 'XXXXX'" is in the file /etc/my.cfg 
$ grep -Fxq "PASSWORD = 'XXXXX'" /etc/my.cfg && echo "YES" 
YES 

kiểm tra Run:

bashtest *.bashtest 

Bạn có thể tìm some examples herehere

2

Có lẽ điều này có thể được sử dụng, hoặc đóng góp vào

https://thorsteinssonh.github.io/bash_test_tools/

Có ý định viết kết quả trong giao thức TAP mà tôi tưởng tượng là tốt cho CI, và tốt cho những người muốn môi trường vỏ. Tôi tưởng tượng một số thứ chạy trong môi trường shell vì vậy, một số có thể tranh luận nên được kiểm tra trong môi trường shell của chúng.

2

tặng một cố gắng để assert.sh

source "./assert.sh" 

local expected actual 
expected="Hello" 
actual="World!" 
assert_eq "$expected" "$actual" "not equivalent!" 
# => x Hello == World :: not equivalent! 

Hy vọng nó sẽ giúp!