[JAVA #17] [Web Automation #17] Selenium With TestNG #6 Soft Assert [KR]

in SCT.암호화폐.Crypto5 years ago (edited)

redsjavahouse1591357_1280.jpg
image source: pixabay


TestNG의 Asserting을 알아본 적이 있다. QA할 때 필수로 사용하는 부분으로 중요하게 다루었는데 사실 Asserting은 Hard Assert라고도 부르는데 한가지 단점이 있다. 아래 예제로 그 단점을 알아본다.

    @Test(description = "글 목록을 불러온다.")
    public void CASE_02_GetPosts() {
        List<WebElement> list = driver.findElements(By.xpath("//div[@id='posts_list']/ul/li"));
        assertTrue(!list.isEmpty(), "글 목록이 있는지 확인");
        for (WebElement post : list) {
            String title = post.findElement(By.xpath("descendant::h2/a")).getText();
            assertNotNull(title,"타이틀 확인 >> " + title);
            String author = post.findElement(By.xpath("descendant::span[@class='user__name']")).getText();
            assertNotNull(author, "작성자 명 확인 >> " + author);
            System.out.println(author + "님의 글: " + title);
        }
    }

👆 풀어 보면

  1. 스팀잇 글 목록을 불러온 후 목록이 비어있지 않은지 체크,
  2. 반복문으로 글의 타이틀이 있는지 체크
  3. 글의 작성자가 있는지 체크하도록 되어 있다.
    모두 정상적으로 노출될 때는 문제가 없다. 다만 개발 오류로 인하여 두번째 Asserting에서 Fail이 떴을 경우 Exception을 던지며 해당 @Test 메서드는 중지되고 다음 @Test로 넘어간다. 즉 세번째 작성자 이름은 체크되지 않는다는 얘기다. 👇
    image.png

QA 자동화에서는 꽤 치명적인 단점일 수 있다. 다행히 이런 문제를 인터넷에서도 많이 연구한 것으로 보인다. 여러가지 해결 방법이 있는데 그 중에서 TestNG가 공식적으로 지원하는 Soft Assert에 대해서 알아보겠다. Soft Assert는 하나의 메서드에 여러개의 Asserting이 있을 경우 그 중에 실패가 뜨더라도 Exception을 catch하는 것으로 보인다. 위 예제에서 Asserting만 Soft Asserting으로 바꿔 보자. SoftAssert sa = new SoftAssert();로 선언한다.

    @Test(description = "글 목록을 불러온다.")
    public void CASE_02_GetPosts() {
        SoftAssert sa = new SoftAssert();
        List<WebElement> list = driver.findElements(By.xpath("//div[@id='posts_list']/ul/li"));
        sa.assertTrue(!list.isEmpty(), "글 목록이 있는지 확인");
        for (WebElement post : list) {
            String title = post.findElement(By.xpath("descendant::h2/a")).getText();
            sa.assertNull(title,"타이틀 확인 >> " + title);
            String author = post.findElement(By.xpath("descendant::span[@class='user__name']")).getText();
            sa.assertNotNull(author, "작성자 명 확인 >> " + author);
            System.out.println(author + "님의 글: " + title);
        }
    }

콘솔에 반복문이 다 수행된 것으로 보아 중지되지 않고 잘 수행되었다는 것을 보여준다. 👇

cryptopie (77)님의 글: Markets Had Gone Wild Again But It Is A Good Thing
bji1203 (73)님의 글: SPT) The Wealthy Gambit 토너먼트 후기
goodreader (61)님의 글: steem-hive中文区[以文会友]20200328(like赞赏公民拍)
rivalhw (75)님의 글: 好文天天赞榜上有名 一起推荐好文章活动将重新启动
freegon (74)님의 글: 엄마에 음식 "쥐고기"
skymin (70)님의 글: 다시 주목 받을 수 있게...
sindoja (69)님의 글: 중국에서 '폭동'이 발발하는 가운데 (부제 : 첫잔속 태풍으로 그칠지 아니면...)
xiaoshancun (67)님의 글: 在幸福里遥望
sean2masaaki (69)님의 글: 석갈비가 끝내주는 황학동 맛집, "나루"
himapan (67)님의 글: [PHOTOGRAPH]Temple & Giant Swing
cryptopie (77)님의 글: I Am Glad That My Vitamin C That I Ordered Will Get Delivered But It Will Take Much Time
jungjunghoon (70)님의 글: 숙성된 돼지고기의 깊은 맛 - 숙달 돼지
gghite (73)제주도 탐험가님의 글: (제주라이프) #6 집밥 릴레이 - 독특한 반찬 고수 넣은 무생채
lnakuma (59)님의 글: 周五了,喘口气
sonki999 (76)님의 글: 바이낸스 VISA 제휴 암호화화폐 직불카드 출시
bluengel (70)님의 글: [ZZAN] 악의 축 처단에 포기란 없다~! <졸업> 짠~! 💙
jhy2246 (70)님의 글: 시골집 매실나무가 너무 예뻐요
ericet (72)ADMIN님의 글: ionomy上交易留点心
honoru (71)님의 글: 構想回饋支持 Patreon月費支持者
virus707 (76)님의 글: 물속의 황금 열쇠

👇 그런데 여기서 또 한가지 문제가 생긴다. Fail이 있어도 무시하고 계속 자동화를 수행하는것은 좋은데 리포트까지 녹색처리 된다. 뭔가 한방에 되는 게 없다. ㅎㅎ
image.png
image.png

두가지를 다 만족하려면 메서드 마지막에 assertAll() 메서드를 추가하면 해결된다. 👇
image.png

두가지 Asserting을 적절하게 사용하면 자동화 효율이 높아질 것으로 보인다.
위 예제에서 1번은 Hard Assert로 체크하고, 2,3번은 Soft Assert로 하면 좋을 것 같다.

하지만 여기서 또 문제.... 메서드마다 맨 마지막에 assertAll()를 넣어줘야 하는데 실수로 안 넣을 경우가 있을 것 같다. 그것도 아주 높은 확률로 말이다. 이 부분은 나중에 방법을 좀 구해보고 오늘은 여기까지. (#전체코드첨부#👇)

package com.steem.webatuo;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;

import io.github.bonigarcia.wdm.WebDriverManager;

public class Steemit {
    WebDriver driver;
    String baseUrl = "https://steemit.com";
    
    @Parameters({"browser"})
    @BeforeClass
    public void SetUp(String browserName) {
        
        if(browserName.equals("chrome")) {
            WebDriverManager.chromedriver().setup();
            driver = new ChromeDriver();    
        }
        else {
            WebDriverManager.firefoxdriver().setup();
            driver = new FirefoxDriver();
        }
            
        driver.get(baseUrl + "/@june0620/feed");
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    }

    @Test(timeOut = 60000, description = "로그인 한다.")
    public void CASE_01_Login() throws InterruptedException {
        // Click the login button
        driver.findElement(By.linkText("로그인")).click();
        // type id
        driver.findElement(By.name("username")).sendKeys("june0620");
        // type pw and submit
        WebElement pw = driver.findElement(By.name("password"));
        assertNotNull(pw, "비밀번호 태그가 노출되는지 확인");
        pw.sendKeys(Password.getPw());
        pw.submit();
        Thread.sleep(5000);
    }
    @Test(description = "글 목록을 불러온다.")
    public void CASE_02_GetPosts() {
        SoftAssert sa = new SoftAssert();
        List<WebElement> list = driver.findElements(By.xpath("//div[@id='posts_list']/ul/li"));
        assertTrue(!list.isEmpty(), "글 목록이 있는지 확인");
        for (WebElement post : list) {
            String title = post.findElement(By.xpath("descendant::h2/a")).getText();
            sa.assertNotNull(title,"타이틀 확인 >> " + title);
            String author = post.findElement(By.xpath("descendant::span[@class='user__name']")).getText();
            sa.assertNotNull(author, "작성자 명 확인 >> " + author);
            System.out.println(author + "님의 글: " + title);
        }
        sa.assertAll();
    }
    @Test(description = "스팀잇에 글 쓰기 한다. ")
    public void CASE_03_Write() throws InterruptedException {
        // Click the write Button
        List<WebElement> writeBtns = driver.findElements(By.xpath("//a[@href='/submit.html']"));
        assertEquals(writeBtns.size(), 1, "글쓰기 버튼이 노출되는지 확인");
        for (WebElement writeBtn : writeBtns) {
            if (writeBtn.isDisplayed()) {
                writeBtn.click();
                Thread.sleep(2000);
                // type Text and Keys
                WebElement editor = driver.findElement(By.xpath("//textarea[@name='body']"));
                String keys = Keys.chord(Keys.LEFT_SHIFT, Keys.ENTER);
                editor.sendKeys("hello!! world", keys, "hello!!! STEEMIT", Keys.ENTER, "안녕, 스팀잇", Keys.ENTER, "你好!似提姆");
                break;
            }
        }
        Thread.sleep(5000);
    }
    @Test(description = "스티미언 검색", dataProvider = "steemians")
    public void CASE_04_Search(String name) {
        driver.get(baseUrl + "/@" + name);
        /*
         * Some actions
         */
    }
    @DataProvider(name = "steemians")
    public Object[][] members() {
        return new Object[][] {
            {"annepink"},
            {"gghite"},
            {"lucky2015"},
            {"honoru"},
            };
    }
    @AfterClass
    public void tearDownClass() {
        driver.quit();
    }
}

.
.
.
.
[Cookie 😅]
Seleniun java lib version: 3.141.59
java version: 13.0.1
참고사이트: https://www.softwaretestingmaterial.com/soft-assert/

Sort:  

我只是来拍手支持👏不用谢哈🌙

不行,还是要谢谢萍萍 😆

俊儿太客气啦🤭给我拍手免谢😂
话说这么久了有没看看自己多少liker了换钱出来买好食啊

@lnakuma的程序上线,我会天天给你拍拍~😄

那先谢谢俊啊!😍 你不给我拍也一样觉得你好!一直那么支持我给我点赞... 感动到我要哭了😭

必须点赞的 😄

多谢拍拍,程序还没上线吗?我搜不到程序😀

吃了吗?请支持中文区的见证人, @abit @bobdos @ety001 @justyy @oflyhigh @partiko (首字母顺序),全投,一个都不要漏。假如我的留言打扰到你,请回复“取消”。