[Bài 18] Lỗi NullPointerException và cách debug trên Eclipse

Trước khi đi vào phần Debug thì mình sẽ viết nốt cái cách mình fix vấn đề ở bài 16 – Đó là việc sử dụng dụng API selenium trực tiếp từ class Test Case. Nếu bạn nào không đọc bài viết trước của mình thì mình có thể tóm tắt lại nội dung như sau:

Mình có 1 test case: sau khi tạo xong 1 bài viết sẽ so sánh cái title của bài viết mình đã tạo vào title của post đó ngoài Front-end xem có đúng ko. 

Cũng giống như các phần khác, mình sẽ tạo ra 1 class cho post ở site Front-end, gọi là PostDetail.

public class PostDetailPage {
	WebDriver driver;

	public PostDetailPage(WebDriver driver) {
		this.driver = driver;
	}
	
	public String getPostTitle() {
		String titlePost = driver.findElement(By.tagName("h1")).getText();
		return titlePost;
	}
}

Sau đó mình sửa lại class Test Case:

Ok rồi, run thử phát. Và đây là cái mình nhận được.

Mình cá là các bạn mới học Selenium mà lập trình chưa vững thì ít nhất cũng đã một lần mắc cái lỗi này. Vậy thì lỗi nào là gì và cách fix ra sao?

NullPointerException là một exception được định nghĩa trong Java, nó thể hiện rằng ta đang sử dụng 1 Object mà nó ko có vị trí nào trên bộ nhớ (null). Và như các bạn nhìn thấy ở trên, đây ko phải là loại lỗi syntax để mà IDE có thể báo lỗi cho mình. Do đó mình cần phải sử dụng cách khác.

Cách fix: Tìm xem cái Object đang bị null nằm ở đâu và fix cho nó hết null. =))))

Bước 1: Tìm Object bị null.

Theo hình ở trên, thì lỗi xảy ra ở dòng thứ 26, nơi sử dụng dòng lệnh Assert kết quả.

Bắt đầu tiến hành Debug:

  • Đặt 1 Break Point ở dòng thứ 26 bằng cách DoubleClick chuột trái.
  • Ở trong dòng thứ 26 này chỉ có 1 Object được sử dụng là Object của class PostDetailPage và Object chỉ đang sử dụng method getPostTitle().
    —> Tiếp tục đặt Break Point ở dòng lệnh bên trong method.
  • Thực hiện run ở chế độ Debug trên Eclipse:

Run ở chế độ Debug thực ra cũng không khác run ở chế độ Run code bình thường, điểm khác duy nhất là hệ thống sẽ dừng lại ở điểm mà ta đặt Break Point.

Giả sử luồng code: A –> B –> C –> D –> E

Nếu C và D là 2 điểm mà ta đặt Break Point thì C là điểm đầu tiên mà hệ thống sẽ dừng lại. Ở tại vị trí này ta có thể xem được các Object ở tại thời điểm này đang có id là bao nhiêu, các biến thì có giá trị như thế nào.

Khi đến chạy đến điểm Break Point đầu tiên, Eclipse sẽ hiển thị thông báo xem chúng ta có muốn hiển thị Layout ở chế độ Debug hay ko? —> Ấn OK luôn. Bạn nào thích thì check luôn vào box “Remember my decision” để lần sau ko bị hỏi lại.

Ở chế độ Debug có những điểm sau cần chú ý:

  • Bảng điều khiển
  1. Resume: Thực hiện tiếp code cho đến hết.
  2. Suspend: Pause lại và giữ nguyên hiện trạng
  3. Terminate: Chấm dứt hẳn phiên debug.
  4. Step into: Nhảy đến cái dòng code tiếp theo trong luồng run code (step by step)
  5. Step Over: Nhảy đến Break Point tiếp theo. Nếu không có Break Point thì nó sẽ run hết function hiện tại trong 1 lượt rồi dừng lại ở function kế tiếp.
  6. Step Return: Khi ra không còn muốn debug step by step nữa, ta muốn nó run toàn bộ cái function trong 1 lần cho đến thời điểm function đó return kết quả.
  • Khu vực code và xem giá trị của các Object và biến hiện tại:

Nhìn vảo bảng giá trị các Object, ta dễ dàng có thể nhận ra postDetailPg đang null


Bước 2: Cách sửa Object bị null.

Ta có thể có nhiều nguyên nhân của việc null này nhưng ta có thể khoanh vùng lại 2 khả năng:

  • Chưa có hàm khởi tạo (constructor)

Cái này bỏ qua vì ta đã có hàm khởi tạo cho nó rồi. (Nhìn lên đoạn code ở phía đầu bài viết)

  • Chưa khởi tạo Object

Hiện tại đúng là chưa có dòng code khởi tạo Object thật, mới chỉ có khai báo biến. Ta add thêm 1 dòng code khởi tạo Object là xong. Run và thấy xanh lè. 😀

Sau khi fix xong bug, muốn trở lại Layout code như bình thường, ấn vào icon Java ở góc phải của Eclipse.


Tóm tắt lại quy trình Debug nói chung:

  1. Dựa vào Stack Trace / Log –> tìm dòng code lỗi.
  2. Đặt Break Point tại dòng code đó và 1 số dòng code trong các function mà dòng code lỗi có sử dụng.
  3. Sử dụng bảng điều khiển linh hoạt để đến được vị trí mình cần hoặc mình nghĩ là sẽ có lỗi.
  4. Theo dõi giá trị các Object và các biến tại từng thời điểm
  5. Tìm ra nguyên nhân gốc rồi fix.

Đôi khi ta không cần dùng đến chức năng Debug để tìm nguyên nhân do nó quá hiển nhiên. Nhưng ta nên tập debug vì Debug sẽ mô tả luồng code chạy, ta sẽ hiểu hơn về ngôn ngữ và check xem framework đã chạy đúng ý ta chưa.

Trên đây là cách mình Debug Java, bạn nào có cách nào hay hơn hoặc thấy mình sai ở đâu đấy, vui lòng comment xuống phía dưới. Thank you!

5 1 vote
Article Rating
Subscribe
Notify of
guest
7 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
trackback

[…] ← Previous Next → […]

Ngabt
Ngabt
4 years ago

Dạ cho e hỏi, e có kịch bản code như bên dưới, e gặp 1 vấn đề là mỗi lần chạy ra 1 kêt quả khác nhau (code vẫn cùng 1 kịch bản), e nghĩ là do đối tưởng element chưa được load trong DOM lên bị fail e đã khắc phục bằng cách cho thêm hàm wait vào nhưng ko hiểu sao kết quả vẫn vậy. Có thể chỉ giúp e là bị sao được ko ạ. Em cảm ơn ạ
package pageHome;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.support.ui.Select;
import java.util.Calendar;
import org.openqa.selenium.JavascriptExecutor; // To scroll using Selenium you can use JavaScriptExecutor
import org.openqa.selenium.*;
public class ReservationList {
public static void main(String[] args) {
// Call driver and web test
System.setProperty(“webdriver.chrome.driver”, “D:\\setup\\ToolsAutoTest\\chromedriver_win32_2\\chromedriver.exe”);
WebDriver driver = new ChromeDriver();
driver.get(“http://123.25.30.62/Login.aspx”);
driver.manage().window().maximize();//To maximize the window. This code may not work with Selenium 3 jars. If script fails you can remove the line below
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
// Input acc and pass
WebElement email = driver.findElement(By.id(“txtLoginUserCd”));
WebElement pass = driver.findElement(By.id(“txtLoginPass”));
email.sendKeys(“of24test”);
pass.sendKeys(“123456a@”);
System.out.println(“Text Field Set”);
// Login
WebElement login = driver.findElement(By.id(“lnkLogin”));
login.click();
// Find menu Reservation –> Reservation List
WebElement Facility = driver.findElement(By.id(“LeftMenu1_liMenuReservation”));
Facility.click();
WebElement Reservation = driver.findElement(By.id(“LeftMenu1_liReservationList”));
Reservation.click();
//Reservation Detail
WebElement Book = driver.findElement(By.id(“plhMain_linkAdd”));
Book.click();
// Product
Select drpProduct = new Select (driver.findElement(By.name(“ctl00$plhMain$ddlProduct”)));
drpProduct.selectByVisibleText(“会議室101”);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
//drpProduct.selectByValue(“4061”);
//Access accout
WebElement Acc = driver.findElement(By.id(“plhMain_lnkRef”));
Acc.click();
WebElement Acc01 = driver.findElement(By.name(“ctl00$plhMain$txtSearchCustomerName”));
Acc01.sendKeys(“nga”);
WebElement Acc02 = driver.findElement(By.id(“plhMain_lnkSearchClient”));
Acc02.click();
WebElement Acc03 = driver.findElement(By.id(“plhMain_rptCustomerList_lnkSelect_4”));
Acc03.click();

//Scroll
//JavascriptExecutor js = (JavascriptExecutor) driver;
//js.executeScript(“window.scrollBy(0,1000)”);// This will scroll down the page by 1000 pixel vertical
//Filter Date
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
WebElement dateFrom = driver.findElement(By.id(“txtFromDate”));
dateFrom.sendKeys(“2020/04/6”);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
Select drpFrom = new Select (driver.findElement(By.name(“ctl00$plhMain$ddlFromTime”)));
drpFrom.selectByValue(“07:15”);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
WebElement dateTo = driver.findElement(By.id(“txtToDate”));
dateTo.sendKeys(“2020/04/7”);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
Select drpTo = new Select (driver.findElement(By.name(“ctl00$plhMain$ddlToTime”)));
drpTo.selectByValue(“08:15”);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
//Select Payment Method
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Select drpPay = new Select (driver.findElement(By.id(“ddlPaymentMethod”)));
drpPay.selectByVisibleText(“現金”);
WebElement Save = driver.findElement(By.xpath(“//dive//a[@id=’plhMain_lnkSave’]”));
Save.click();
}

}

Ngabt
Ngabt
4 years ago

Em vừa gửi lỗi hỏi đây ạ, do cho e hỏi tab console của em báo như này, thì bị lỗi gì ạ?
Starting ChromeDriver 80.0.3987.106 (f68069574609230cf9b635cd784cfb1bf81bb53a-refs/branch-heads/3987@{#882}) on port 20549
Only local connections are allowed.
Please protect ports used by ChromeDriver and related test frameworks to prevent access by malicious code.
[1583476086.964][WARNING]: Timed out connecting to Chrome, retrying…
Mar 06, 2020 1:28:09 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
[1583476089.275][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476089.416][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476090.678][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476090.779][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476090.881][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476090.982][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476091.083][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476091.184][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476091.285][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476091.385][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476091.489][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476091.590][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476091.698][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476091.800][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476091.901][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476092.009][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476092.110][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476092.212][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476092.313][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476092.414][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476092.515][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476094.814][WARNING]: Timed out connecting to Chrome, retrying…
Text Field Set
[1583476097.409][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476097.515][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476097.674][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476098.428][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476100.699][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476100.800][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476100.902][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476101.009][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476102.055][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476102.156][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476102.257][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476102.358][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476102.461][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476102.565][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476102.666][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476102.770][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476102.873][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476102.974][SEVERE]: Timed out receiving message from renderer: 0.100
[1583476103.076][SEVERE]: Timed out receiving message from renderer: 0.100
Exception in thread “main” org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
(Session info: chrome=80.0.3987.132)
For documentation on this error, please visit: https://selenium.dev/exceptions/#stale_element_reference
Build info: version: ‘4.0.0-alpha-4’, revision: ‘c2d955b49e’
System info: host: ‘DESKTOP-I9AALH1’, ip: ‘192.168.96.47’, os.name: ‘Windows 10’, os.arch: ‘amd64’, os.version: ‘10.0’, java.version: ‘1.8.0_241’
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 80.0.3987.132, chrome: {chromedriverVersion: 80.0.3987.106 (f68069574609…, userDataDir: C:\Users\SMS-NG~1\AppData\L…}, goog:chromeOptions: {debuggerAddress: localhost:61673}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify}
Session ID: 43265508a9ebbd3ffd04b2803bfacfed
at pageHome.ReservationList.main(ReservationList.java:42)

Nga
Nga
4 years ago

E thay bằng Explicit Wait thì lại báo sai như này: Exception in thread “main” java.lang.Error: Unresolved compilation problems:
WebDriverWait cannot be resolved to a type
WebDriverWait cannot be resolved to a type

at pageHome.ReservationList.main(ReservationList.java:17)
Sai như trên e sửa thì lại báo dùng FluentWait vậy là sao a nhỉ