Những người làm phần mềm hẳn ai cũng đã biết đến công đoạn rất quan trọng sau khi thành phẩm là "kiểm thử" (test). Một trong những kiểu kiểm thử (test case) cần phải làm là kiểm thử khả năng chịu đựng của hệ thống (load test). Có một công cụ rất mạnh để tự động hóa quá trình này, tiết kiệm thời gian và công sức cho đội kiểm thử đó là Grinder.

Giới thiệu

Tại sao lại là Grinder mà không phải là một công cụ nào khác? Đơn giản là vì Grinder sử dụng Jython - Python chạy trên nền Java - một sự kết hợp tuyệt vời của một ngôn ngữ rất mềm dẻo, mạnh mẽ (Python) với một khung nền có thể chạy trên mọi hệ điều hành (Java).

Grinder bao gồm 3 thành phần:

  • Console: đây là thành phần đóng vai trò điều khiển và tiếp nhận kết quả kiểm thử trả về.
  • Agent process: đây là thành phần nhận lệnh từ Console và điều khiển các worker process.
  • Worker process: đây là các kịch bản kiểm thử do người dùng định nghĩa.

Như vậy, tại máy dùng để theo dõi và hiển thị kết quả kiểm thử, chạy Console. Tại các máy trạm chịu trách nhiệm chạy các kịch bản kiểm thử, chạy Agent process. Các kịch bản kiểm thử sẽ được tự động chuyển về cho các Agent process từ Console khi người dùng ra lệnh chạy.

Chuẩn bị

Để chạy được Grinder cần phải cài đặt các biến môi trường trỏ về đúng thư mục cài đặt Grinder và các thành phần liên quan.

Đối với Windows

  • Tạo tập tin kịch bản gọi mõi khi chạy setGrinderEnv.cmd:

    set GRINDERPATH=(full path to grinder install directory)
    set GRINDERPROPERTIES=(full path to grinder.properties)\grinder.properties
    set CLASSPATH=%GRINDERPATH%\lib\grinder.jar;%CLASSPATH%
    set JAVA_HOME=(full path to java install directory)
    PATH=%JAVA_HOME%\bin;%PATH%
    
  • Hoặc gán trực tiếp biến môi trường mỗi khi khởi động bằng cách:

    • Vào System Properties chọn tab Advanced chọn tiếp Environment Variables
    • Chọn New và thêm vào tên biến và đường dẫn như trên.

Đối với Unix

  • Tạo tập tin kịch bản setGrinderEnv.sh:

    #!/usr/bin/ksh
    GRINDERPATH=(full path to grinder install directory)
    GRINDERPROPERTIES=(full path to grinder.properties)/grinder.properties
    CLASSPATH=$GRINDERPATH/lib/grinder.jar:$CLASSPATH
    JAVA_HOME=(full path to java install directory)
    PATH=$JAVA_HOME/bin:$PATH
    export CLASSPATH PATH GRINDERPROPERTIES
    
  • Hoặc gán trực tiếp mỗi khi đăng nhập vào người dùng bằng cách thêm vào trong tập tin /home/$USER/.bashrc:

    export GRINDERPATH=(full path to grinder install directory)
    export GRINDERPROPERTIES=(full path to grinder.properties)/grinder.properties
    export CLASSPATH=$GRINDERPATH/lib/grinder.jar:$CLASSPATH
    export JAVA_HOME=(full path to java install directory)
    

Cấu hình

Tập tin thuộc tính grinder.properties thường gồm các tham số sau:

Tên tham số Giải thích Giá trị mặc định
grinder.processes Số lượng tiến trình worker mà một agent khởi tạo 1
grinder.threads Số lượng tiểu trình mà mỗi tiến trình worker sinh ra 1
grinder.runs Số lần chạy kịch bản kiểm thử mà mỗi tiểu trình chạy. 0 nghĩa là chạy lặp đi lặp lại. Tham số này nên để là 0 khi sử dụng Console để điều khiển hoạt động của các agent. 1
grinder.processIncrement Nếu đặt, agent sẽ tăng số lượng tiếng trình worker lên sau mỗi nhịp grinder.processIncrementInterval. 0 (Khởi động tất cả các tiến trình worker cùng lúc.)
grinder.processIncrementInterval Sử dụng cùng với tham số grinder.processIncrement, tham số này xác định nhịp tăng tiến trình worker tính theo mili giây. 60000
grinder.initialProcesses Sử dụng cùng với tham số grinder.processIncrement, tham số này xác định số lượng tiến trình worker khởi động. Giá trị của grinder.processIncrement.
grinder.duration Thời gian mỗi tiến trình worker chạy. Tham số này có thể xác định cùng với tham số grinder.runs, điều đó có nghĩa là tiến trình worker sẽ chấm dứt nếu hết thời gian chạy hoặc số lượng tiến trình worker đạt tối đa. 0 (Không kết thúc.)
grinder.script Tên tập tin kịch bản sẽ chạy. grinder.py
grinder.jvm Sử dụng máo ảo Java (JVM) khác. Mặc định là java nên không cần phải khai báo nếu đã có sẵn trong đường dẫn (PATH). java
grinder.jvm.classpath Dùng để xác định đường dẫn đến các lớp sử dụng cho tiến trình worker. Bất cứ đường dẫn nào xác định ở đây sẽ được thêm vào trong đường dẫn classpath sử dụng để khởi động tiến trình Grinder.  
grinder.jvm.arguments Các tham số phụ thêm cho tiến trình worker.  
grinder.logDirectory Thư mục lưu tập tin log. Tự động tạo nếu chưa có. Thư mục cục bộ
grinder.numberOfOldLogs Số lượng nhật kí được lưu lại từ lần chạy trước đó. 1
grinder.hostID Thay thế chuỗi host sử dụng trong tên tập tin nhật kí và trong nhật kí. Tên máy
grinder.consoleHost Địa chỉ IP hoặc tên máy sử dụng cho kết nối giữa các agent, tiến trình worker và console. Tất cả các giao tiếp mạng của máy.
grinder.consolePort Cổng để agent và tiến trình worker sử dụng để kết nối đến console. 6372
grinder.useConsole Nếu đặt là false, agent và tiến trình worker sẽ không sử dụng console. true
grinder.reportToConsole.interval Khoảng thời gian mỗi tiến trình gửi cập nhật về cho console. Tham số này cũng xác định khoảng thời gian các tập tin dữ liệu được làm mới. Giá trị tính theo mili giây. 500
grinder.initialSleepTime Khoảng thời gian tối đa mỗi tiểu trình đợi trước khi bắt đầu. Không giống như thời gian ngừng trong kịch bản, tham số này thay đổi ngẫu nhiên giữa 0 và giá trị được đặt. Bị ảnh hưởng bởi tham số grinder.sleepTimeFactor, còn tham số grinder.sleepTimeVariation thì không. Giá trị tính theo mili giây. 0
grinder.sleepTimeFactor Thêm một hệ số vào thời gian chờ đã đặt, thông qua một thuộc tính hay trong kịch bản. Đặt giá trị này là 0.1 kịch bản sẽ chạy nhanh hơn mười lần. 1
grinder.sleepTimeVariation Thông thường, Grinder thay đổi thời gian chờ xác định trong kịch bản tùy theo sự phân chia bình thường. Tham số này xác định một dải phân đoạn mà đa số (chiếm 99.75%) là sẽ rơi vào trong dải này. Ví dụ, nếu thời gian chờ xác định là 1000 và sleepTimeVariation đặt là 0.1, khi đó 99.75% các giá trị thời gian chờ sẽ nằm trong khoảng 900 và 1100 milli giây. 0.2
grinder.logProcessStreams Đặt là false để tắt tính năng ghi nhật kí những thông báo và lỗi hiển thị của tiến trình worker. Dùng tham số này để giảm tải cho các tiểu trình tại máy trạm. true
grinder.reportTimesToConsole Đặt là false để tắt tính năng phản hồi thông tin thời gian về cho console, các thông tin thống kê khác vẫn được phản hồi. true
grinder.debug.singleprocess Nếu đặt là true, agent sẽ phát sinh tiểu trình để chạy kịch bản thay vì tiến trình, sử dụng một bộ nạp lớp đặc biệt để cô lập engine ra. Điều này cho phép engine dễ gỡ rối hơn. Mục đích chính của công cụ này là gỡ rối Grinder engine, tuy nhiên nó cũng có thể dùng cho người dùng chuyên nghiệp vào các mục đích khác. false
grinder.useNanoTime Nết đặt là true, System.nanoTime() sẽ được dùng để đo thời gian thay vì System.currentTimeMills(). Grinder sẽ vẫn phản hồi thời gian tính bằng mili giây. Độ chính xác của những phương pháp này phụ thuộc vào sự hiện thực hóa JVM và hệ điều hành. Tham số true chỉ dùng cho J2SE 5 hoặc lớn hơn. false

Ví dụ

Thông thường, một tập tin cấu hình đơn giản chỉ cần các thông số sau:

grinder.process 1
grinder.threads 1
grinder.runs 1
grinder.script sample.py

Nếu chạy ở chế độ có Console thì cần thêm:

grinder.useConsole true
grinder.consoleHost x.x.x.x (IP hoặc tên máy Console)
grinder.consolePort xxx (cổng quy định bởi Console)

Chạy

Để chạy Grinder có thể đơn giản như sau:

  • Chạy Console:

    java net.grinder.Console
    
  • Chạy Agent:

    java net.grinder.Grinder
    

Hoặc tạo tập tin kịch bản như sau:

Đối với Windows

startAgent.cmd

call (path to setGrinderEnv.cmd)\setGrinderEnv.cmd
echo %CLASSPATH%
java -cp %CLASSPATH% net.grinder.Grinder %GRINDERPROPERTIES%

startConsole.cmd

call (path to setGrinderEnv.cmd)\setGrinderEnv.cmd
java -cp %CLASSPATH% net.grinder.Console

Đối với Unix

startAgent.sh

#!/usr/bin/ksh
. (path to setGrinderEnv.sh)/setGrinderEnv.sh
java -cp $CLASSPATH net.grinder.Grinder $GRINDERPROPERTIES

startConsole.sh

#!/usr/bin/ksh
. (path to setGrinderEnv.sh)/setGrinderEnv.sh
java -cp $CLASSPATH net.grinder.Console

Công việc tiếp theo chỉ là... viết kịch bản kiểm thử và chạy.

Tự động hóa

Đến đây hẳn nhiều người, nhất là những lập trình viên không (chưa) biết ngôn ngữ Python sẽ tiếc nuối vì không biết viết mã cho kịch bản kiểm thử như thế nào. Nhưng có một cách để những lập trình viên này vẫn có thể dùng công cụ kiểm thử mạnh mẽ Grinder mà không cần phải biết viết một dòng mã Python nào. Từ phiên bản 3.0 trở lên, Grinder cung cấp một môi trường proxy kiểm soát dữ liệu vào ra để tự động tạo mã kịch bản tương ứng. Điều đó có nghĩa là, kịch bản sẽ tự động được tạo ra theo đúng những thao tác chuột và bàn phím mà những người kiểm thử làm. Và tất nhiên cách này chỉ dùng cho những kiểm thử đối với các ứng dụng web.

Để khởi động Grinder proxy:

Đối với Windows

startProxy.cmd

call (path to setGrinderEnv.cmd)\setGrinderEnv.cmd
java -cp %CLASSPATH% net.grinder.TCPProxy -console -http > script_name.py

Đối với Unix

startProxy.sh

#!/usr/bin/ksh
. (path to setGrinderEnv.sh)/setGrinderEnv.sh
java -cp $CLASSPATH net.grinder.TCPProxy -console -http > script_name.py

Sau đó thiết đặt trình duyệt cho trỏ đến proxy là localhost với cổng 8081 và bắt đầu các thao tác kiểm thử.

Tổng kết

Trên đây là những bước cơ bản nhất để có thể làm quen với một công cụ kiểm thử vô cùng mạnh mẽ, đơn giản, dễ dùng và đặc biệt là hoàn toàn miễn phí. Mặc dù chạy trên nền Java nhưng trong quá trình thử nghiệm cũng như sử dụng để kiểm thử hệ thống Online Trading của công ty Chứng khoán VNDirect, Grinder chạy rất nhẹ nhàng, không tốn nhiều RAM như tôi lo ngại, thậm chí tôi sử dụng chính các máy của người dùng làm agent trong khi mọi người vẫn làm việc mà không hề thấy hệ thống bị kéo chậm lại hay có vấn đề gì xảy ra. Việc làm quen với Grinder cũng không mất quá nhiều thời gian, kể cả với một tay ngang như tôi. Grinder thật sự rất ấn tượng. Và điểm nổi trội nhất của Grinder đó là nó cho phép người dùng tự định nghĩa kịch bản kiểm thử bằng một ngôn ngữ mạnh mẽ và mềm dẻo - Python.