Phát hiện, xử lý các lỗi và kiểm thử (testing) trong Android Studio (3.6 trở lên)

Ứng dụng minh họa

Bài viết này sử dụng ứng dụng đơn giản DebuggingApp với tập tin activity_main.xml:


<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<TextView
android:id="@+id/txtKetqua"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textColor="@color/colorPrimary"
android:textSize="50sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Và tập tin MainActivity.java:


package com.example.debuggingapp;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {


  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    TextView txtKetqua = findViewById(R.id.txtKetqua);
    txtKetqua.setText(String.valueOf(add(4, 5)));
  }
  public int add(int a, int b){
   return a+b;
  }
}

Lớp Log và cửa sổ Logcat

Một trong những cách phổ biến nhất để phát hiện các lỗi trong ứng dụng Android là dùng các thông điệp từ lớp Log trong cửa sổ Logcat (View > Tool Windows > Logcat). Để dùng lớp Log chúng ta cần khai báo:


import android.util.Log;

Để hiển thị thông điệp trong cửa sổ Logcat, chúng ta có thể dùng một trong các phương thức tĩnh sau:

  • d (viết tắt của Debug)
  • i (viết tắt của Info)
  • e (viết tắt của Error)
  • w (viết tắt của Warn)

Mỗi phương thức thường có hai tham số, ví dụ phương thức Log.d như sau:


Log.d("MainActivity","Hello World");

  • Tham số đầu tiên là một thẻ dùng để lọc thông điệp trong cửa sổ Logcat. Thông thường giá trị của tham số này là tên của Activity phát sinh thông điệp.
  • Tham số thứ hai là thông điệp.

Khi thực thi ứng dụng, vì có quá nhiều thông điệp trong cửa sổ Logcat nên chúng ta có thể gõ giá trị của tham số thứ nhất (MainActivity) phương thức Log.d vào thanh tìm kiếm để xem thông điệp hiển thị (Hello World) một cách nhanh chóng:

Công cụ Debug

Chế độ Debug là công cụ hiệu quả nhất trong việc phát hiện, chỉnh sửa lỗi và cải thiện hiệu năng ứng dụng trong môi trường Android Studio. Để chạy ứng dụng trong chế độ Debug chúng ta vào mục Run > Debug ‘app’ hay nút Debug ‘app’

Nếu ứng dụng chúng ta đang chạy, muốn chuyển qua chế độ Debug thì chọn Attach Debugger to Android Process

Trong cửa sổ Choose Process nhấn OK

Khi ứng dụng đang ở trong chế độ Debug, mọi thứ sẽ được giám sát qua cửa sổ Debug. Nếu cửa sổ Debug không xuất hiện có thể mở cửa sổ này bằng cách vào View > Tool Windows > Debug. Một cửa sổ Debug thông thường như sau (chú ý dòng …is waiting for the debugger…)

Chú ý hai tab mặc định là DebuggerConsole. Chọn tab Debugger sẽ xuất hiện các cửa sổ phục vụ chủ yếu cho quá trình debug chương trình:

Các cửa sổ bao gồm Frames (bên trái), Variables (giữa) và Watches (bên phải). Các cửa sổ này sẽ được tìm hiểu chi tiết hơn trong phần sau của bài viết này.

Thiết lập điểm ngắt (breakpoint)

Một điểm ngắt hay điểm dừng (a breakpoint) là nơi chúng ta muốn ngừng việc thực thi của ứng dụng để tiến hành một vài nhiệm vụ nào đó như kiểm tra biến, tính toán biểu thức hay thực thi dòng mã để xác định nguyên nhân lỗi.

Để thiết lập điểm ngắt tại một dòng mã nào đó chúng ta chọn dòng lệnh đó và nhấp chuột trái vào bên trái con số chỉ số dòng trong vùng xám bên trái:

Dấu chấm đỏ bao gồm dấu check thể hiện chương trình đang trong chế độ Debug. Quá trình thực thi của ứng dụng sẽ dừng tại điểm ngắt và trạng thái của ứng dụng sẽ được  thể hiện qua các cửa sổ như hình sau:

Cùng nhìn rõ hơn trong khung Frames

Cửa sổ Frames hiển thị các lớp và phương thức được gọi trong ứng dụng và phương thức được gọi gần nhất sẽ ở trên cùng (trong hình trên là phương thức onCreate). Nhấn vào tab Threads để xem chi tiết hơn:

Lúc này ứng dụng đang chạy trong tiểu trình chính (main thread) và đang thực thi phương thức onCreate trong MainActivity.

Như cái tên của nó phản ánh, cửa sổ Variables cho phép theo dõi các biến và giá trị của chúng như hình

Từ this hàm ý cho MainActivity, txtKetqua là biến (kiểu TextView). Các biến có thể được mở rộng  với các thuộc tính (properties)

Giá trị các biến sẽ được giám sát chặt chẽ hơn thông qua cửa sổ Watches.

Thực thi từng dòng mã trong chế độ Debug

Trong cửa sổ Debug, chúng ta có thể thực thi từng dòng mã của ứng dụng với các chức năng

  • Step Over: thực thi từng dòng lệnh
  • Step Into: nhảy vào trong phương thức được gọi bởi dòng lệnh hiện tại
  • Step Out: thoát khỏi phương thức trở về dòng lệnh hiện tại (nơi gọi phương thức)

Xem hình bên dưới minh họa các thao tác Step Over, Step IntoStep Out

Unit Testing

Unit Testing là phương pháp kiểm thử phần mềm dựa trên các đơn vị kiểm thử (hay unit test). Trong các ngôn ngữ hướng đối tượng (ví dụ C# hay Java), các đơn vị kiểm thử này có thể là các phương thức hay lớp. Một đơn vị kiểm thử được dùng để kiểm tra một đơn vị công việc (unit of work) với một kết quả giả định nào đó; Nếu kết quả thực thi của đơn vị công việc cần kiểm tra khác với kết quả giả định thì đơn vị kiểm thử thất bại.

Unit Testing có thể được thực hiện dễ dàng nhờ các framework. Framework phổ biến hỗ trợ cho các nhà phát triển Java là Junit. Có thể dễ dàng kiểm tra các lớp kiểm thử này trong mục app > java

Mỗi ứng dụng trong Android Studio sẽ được đính kèm với các lớp hỗ trợ quá trình kiểm thử bao gồm kiểm thử đơn vị (unit tests) và kiểm thử trên thiết bị ảo hay thực (instrumented tests). Tìm hiểu về hai kiểu kiểm thử trong Android Studio tại https://developer.android.com/studio/test

Lớp unit test hỗ trợ kiểm thử trên máy ảo Java cục bộ (JVM) và không phụ thuộc vào các lớp thư viện Android, trong khi đó, lớp instrumented test khá chậm, liên quan nhiều thư viện Android và chỉ phù hợp khi kiểm thử ứng dụng trên các thiết bị thực (hay ảo). Tham khảo thêm về instrumented test tại https://developer.android.com/training/testing/unit-testing/instrumented-unit-tests

Bài viết này chỉ đề cập đến lớp unit test và như hình trên là lớp ExampleUnitTest với nội dung mặc định như sau:


package com.example.debuggingapp;

import org.junit.Test;
import static org.junit.Assert.*;

/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
  @Test
  public void addition_isCorrect() {
    assertEquals(4, 2 + 2);
  }
}

Để ý rằng chúng ta cần import các lớp TestAssert từ thư viện jUnit. Phương thức addition_isCorrect() là một đơn vị kiểm thử (unit) được đánh dấu bằng chỉ danh @Test nhằm mục đích kiểm tra tính chính xác của toán tử cộng. Phương thức này gọi phương thức assertEquals từ lớp Assert để kiểm tra kết quả kỳ vọng (tham số đầu tiên) và kết quả thực (tham số thứ hai).

Để thực thi lớp kiểm thử, nhấn chuột phải vào thư mục tương ứng chứa lớp đó và chọn Run ‘Tests in ‘debuggingapp’’

Kết quả xuất hiện cửa sổ Run và thông điệp Tests passed nếu kết quả là chính xác:

Bây giờ, trong lớp ExampleUnitTest thay đổi giá trị trong phương thức


assertEquals:assertEquals(4, 3 + 2);

Thực thi lại việc kiểm thử nhưng lần này nhấn chuột phải trực tiếp vào phương thức addition_isCorrect trong cửa sổ Run và chọn Run ‘addion_isCorrect()’

Kết quả:

Vì 3 + 2 = 5 khác 4 nên kết quả quá trình kiểm thử là Tests failed.

Bên cạnh đơn vị kiểm thử mặc định (phương thức addition_isCorrect), chúng ta có thể thêm các đơn vị kiểm thử khác phục vụ cho nhiều mục đích khác nhau. Giả sử chúng ta muốn kiểm tra tính chính xác của phương thức add trong lớp MainActivity của ứng dụng DebuggingApp, chúng ta thêm phương thức addMethodTest đến lớp ExampleUnitTest:


@Test
public void addMethodTest() {

}

Nếu lúc này chúng ta thực thi lại kiểm thử, trong cửa sổ Run sẽ xuất hiện thêm phương thức mới:

Thêm biến thành viên kiểu lớp MainActivity đến lớp ExampleUnitTest, tạo một thể hiện lớp MainActivity và kiểm thử phương thức add dùng phương thức assertEquals trong phương thức addMethodTest. Nội dung lớp ExampleUnitTest lúc này như sau:


public class ExampleUnitTest {
  private MainActivity mainActivity;
  @Test
  public void addition_isCorrect() {
    assertEquals(4, 2+2);
  }
  @Test
  public void addMethodTest() {
    mainActivity = new MainActivity();
    assertEquals(-1, mainActivity.add(-3,2));
  }
}

Chọn phương thức addMethodTest trong cửa sổ Run và thực thi:

Thay đổi giá trị tham số thứ nhất của phương thức add từ -3 thành -2 và thực thi kiểm thử lại

Nhấn chuột trái vào phương thức addMethodTest tại khung bên trái trong cửa sổ Run để xem lỗi chi tiết:

Lời kết

Trong bài viết này chúng ta đã tìm hiểu qua các công cụ quan trọng giúp phát hiện, xử lý và cải thiện hiệu năng ứng dụng trong môi trường Android Studio. Hiểu rõ và sử dụng thành thạo các công cụ này là một trong những kỹ năng bắt buộc với người phát triển ứng dụng Android.

Chia sẻ:

Thích bài này:

Thích

Đang tải…