Testng: ์ˆ˜ํผ ํด๋ž˜์Šค์˜ @BeforeClass ๋ฐ @AfterClass๋Š” ํด๋ž˜์Šค์—์„œ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•  ๋•Œ ๊ทธ๋ฃน์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2019๋…„ 08์›” 21์ผ  ยท  19์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: cbeust/testng

ํ…Œ์ŠคํŠธNG ๋ฒ„์ „

์ˆ˜์ •๋จ: 6.14.3

์˜ˆ์ƒ๋˜๋Š” ํ–‰๋™

์Šˆํผํด๋ž˜์Šค์˜ @BeforeClass ๋ฐ @AfterClass ๋Š” ๊ทธ๋ฃน ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์กด์ค‘ํ•ด์•ผ ํ•˜๋ฉฐ ํ•ด๋‹น ๊ทธ๋ฃน๊ณผ ํ•จ๊ป˜ ํด๋ž˜์Šค ์ „ํ›„์— ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ ํ–‰๋™

6.14.3 @BeforeClass ๋ฐ @AfterClass ๋Š” ์†Œ์† ๊ทธ๋ฃน์— ๊ด€๊ณ„์—†์ด ๊ฐ ํด๋ž˜์Šค์— ๋Œ€ํ•ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ์˜ˆ์ œ ํ…Œ์ŠคํŠธ ๋ฐ ์ถœ๋ ฅ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. @BeforeClass ๋ฐ @AfterClass ๊ฐ€ ์Šˆํผํด๋ž˜์Šค ๋Œ€์‹  ๊ฐ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ์žˆ์œผ๋ฉด ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ์Šˆํผํด๋ž˜์Šค๊ฐ€ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ๋Œ€ํ•œ ์„ค์ • ๋ฐ ๋ถ„ํ•ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•˜๋Š” ๋ชฉ์ ์€ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ์ˆ˜๋งŽ์€ ์ƒ์šฉ๊ตฌ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

7.0.0์—์„œ @BeforeClass and @AfterClass` ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ ์ „์— ๊ฐ ํด๋ž˜์Šค์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ ํ›„์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

๋Ÿฌ๋„ˆ์—์„œ ๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

  • [ ] ๊ป๋ฐ๊ธฐ
  • [ ] ๋ฉ”์ด๋ธ
  • [x] ๊ทธ๋ž˜๋“ค
  • [ ] ๊ฐœ๋ฏธ
  • [ ] ์ดํด๋ฆฝ์Šค
  • [ ] ์ธํ…”๋ฆฌ์ œ์ด
  • [ ] ๋„ท๋นˆ

ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ƒ˜ํ”Œ

๊ทธ๋ฃน "a"๊ฐ€ ์žˆ๋Š” ํด๋ž˜์Šค A

@Test(groups = ["a"])
class ClassA : BaseTest() {
    <strong i="30">@Test</strong>
    fun someTest() {
        println("Test in class A with group A ran on ${Thread.currentThread().id} thread")
    }
}

๊ทธ๋ฃน "b"๊ฐ€ ์žˆ๋Š” ํด๋ž˜์Šค B

@Test(groups = ["b"])
class ClassB : BaseTest() {
    <strong i="34">@Test</strong>
    fun someTest() {
        println("Test in class B with group B ran on ${Thread.currentThread().id} thread")
    }
}

๊ฐ ๊ทธ๋ฃน์— ๋Œ€ํ•ด @BeforeClass ๋ฐ @AfterClass ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š” ์Šˆํผํด๋ž˜์Šค.

open class BaseTest {
    @BeforeClass(groups = ["a"])
    fun beforeClassA() {
        println("Ran before class A on ${Thread.currentThread().id} thread")
    }

    @BeforeClass(groups = ["b"])
    fun beforeClassB() {
        println("Ran before class B on ${Thread.currentThread().id} thread")
    }

    @AfterClass(groups = ["a"])
    fun afterClassA() {
        println("Ran after class A on ${Thread.currentThread().id} thread")
    }

    @AfterClass(groups = ["b"])
    fun afterClassB() {
        println("Ran after class B on ${Thread.currentThread().id} thread")
    }
}

testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="All tests" verbose="1" parallel="classes" thread-count="2" >
    <test name="Tests">
        <classes>
            <class name="test.ClassA" />
            <class name="test.ClassB" />
        </classes>
    </test>
</suite>

์‹ค์ œ ์ถœ๋ ฅ:

Ran before class A on 14 thread
Ran before class A on 15 thread
Ran before class B on 14 thread
Ran before class B on 15 thread
Test in class A with group A ran on 14 thread
Test in class B with group B ran on 15 thread
Ran after class A on 14 thread
Ran after class A on 15 thread
Ran after class B on 14 thread
Ran after class B on 15 thread

์˜ˆ์ƒ ์ถœ๋ ฅ:

Ran before class A on 14 thread
Ran before class B on 15 thread
Test in class A with group A ran on 14 thread
Test in class B with group B ran on 15 thread
Ran after class A on 14 thread
Ran after class B on 15 thread
beforafter groups Needs Query to be answered

๋ชจ๋“  19 ๋Œ“๊ธ€

์‹ค์ œ๋กœ ์œ„์˜ ๋™์ž‘์€ 6.14.3์— ์žˆ์Šต๋‹ˆ๋‹ค. 7.0.0์—์„œ๋Š” ๋” ์ด์ƒํ•ฉ๋‹ˆ๋‹ค. ํ™•์ธ์„ ์œ„ํ•ด ํƒ€์ž„์Šคํƒฌํ”„๋„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

7.0.0์˜ ์ถœ๋ ฅ:

Ran before class A on 15 thread, 23:43:10.723
Ran before class A on 14 thread, 23:43:10.723
Ran before class B on 15 thread, 23:43:10.830
Ran before class B on 14 thread, 23:43:10.830
Ran after class B on 15 thread, 23:43:10.952
Ran after class A on 14 thread, 23:43:10.952
Ran before class A on 14 thread, 23:43:11.054
Ran before class B on 15 thread, 23:43:11.054
Test in class A with group A ran on 14 thread, 23:43:11.265
Test in class B with group B ran on 15 thread, 23:43:11.265
Ran before class A on 14 thread, 23:43:11.465
Ran after class B on 15 thread, 23:43:11.465
Ran before class B on 15 thread, 23:43:11.569
Ran after class A on 14 thread, 23:43:11.569
Ran after class A on 14 thread, 23:43:11.677
Ran after class A on 15 thread, 23:43:11.677
Ran after class B on 14 thread, 23:43:11.777
Ran after class B on 15 thread, 23:43:11.778

@MindaugasMateika - ๋ฌธ์ œ๋Š” ์ œํ’ˆ๊ตฐ xml ํŒŒ์ผ์— ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฃน๋ณ„๋กœ ์‹คํ–‰ํ•˜๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฃน๋ณ„๋กœ ์‹คํ–‰ํ•˜๋ ค๋ฉด ์ œํ’ˆ๊ตฐ ํŒŒ์ผ์—์„œ <groups> ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํ•ด๋‹น ๊ทธ๋ฃน์„ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ทธ๋ฃน ์‹คํ–‰์ด ํŠธ๋ฆฌ๊ฑฐ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(ํ…Œ์ŠคํŠธ/๊ตฌ์„ฑ์ด ๊ทธ๋ฃน์— ์†ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด).

์ด ๋ฌธ์ œ๋ฅผ ๋‹ซ์Šต๋‹ˆ๋‹ค.
์‹œ๋„ํ•ด ๋ณด์‹œ๊ณ  ๋ฌธ์ œ๊ฐ€ ๊ณ„์† ๋ฐœ์ƒํ•˜๋ฉด ์˜๊ฒฌ์„ ๋ง์”€ํ•ด ์ฃผ์‹ญ์‹œ์˜ค.

@krmahadevan ๋‹˜ , xml์— ๊ทธ๋ฃน์„ ์ถ”๊ฐ€ํ–ˆ์ง€๋งŒ ๋™์ผํ•œ ๋™์ž‘์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="All tests" verbose="1" parallel="classes" thread-count="2" >
    <test name="Tests">
        <groups>
            <run>
                <include name="a" />
                <include name="b" />
            </run>
        </groups>
        <classes>
            <class name="test.ClassA" />
            <class name="test.ClassB" />
        </classes>
    </test>
</suite>
Ran before class A on 15 thread, 10:51:48.794
Ran before class A on 14 thread, 10:51:48.794
Ran before class B on 14 thread, 10:51:48.902
Ran before class B on 15 thread, 10:51:48.902
Ran after class A on 14 thread, 10:51:49.014
Ran after class B on 15 thread, 10:51:49.017
Ran before class A on 14 thread, 10:51:49.116
Ran before class B on 15 thread, 10:51:49.117
Test in class A with group A ran on 14 thread, 10:51:49.444
Test in class B with group B ran on 15 thread, 10:51:49.444
Ran after class B on 15 thread, 10:51:49.624
Ran before class A on 14 thread, 10:51:49.624
Ran after class A on 14 thread, 10:51:49.725
Ran before class B on 15 thread, 10:51:49.726
Ran after class A on 14 thread, 10:51:49.828
Ran after class A on 15 thread, 10:51:49.828
Ran after class B on 14 thread, 10:51:49.931
Ran after class B on 15 thread, 10:51:49.931



md5-37e721bbba1e94aae099dbc7071b38c3



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="All tests" verbose="1" parallel="classes" thread-count="2" >
    <test name="Tests">
        <groups>
            <run>
                <include name="a" />
            </run>
        </groups>
        <classes>
            <class name="test.ClassA" />
        </classes>
    </test>
    <test name="Tests B">
        <groups>
            <run>
                <include name="b" />
            </run>
        </groups>
        <classes>
            <class name="test.ClassB" />
        </classes>
    </test>
</suite>



md5-38a48c328d261b22db36e9db68bb81ec



Ran before class A on 14 thread, 10:55:06.758
Ran after class A on 14 thread, 10:55:06.875
Ran before class A on 14 thread, 10:55:06.975
Test in class A with group A ran on 14 thread, 10:55:07.278
Ran before class A on 14 thread, 10:55:07.522
Ran after class A on 14 thread, 10:55:07.625
Ran after class A on 14 thread, 10:55:07.728
Ran before class B on 15 thread, 10:55:07.840
Ran after class B on 15 thread, 10:55:07.941
Ran before class B on 15 thread, 10:55:08.044
Test in class B with group B ran on 15 thread, 10:55:08.151
Ran after class B on 15 thread, 10:55:08.254
Ran before class B on 15 thread, 10:55:08.356
Ran after class B on 15 thread, 10:55:08.458

@MindaugasMateika - ์—ฌ๊ธฐ์— ๋ช‡ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ํด๋ž˜์Šค ์ˆ˜์ค€ ์ฃผ์„์„ ์ œ๊ฑฐํ•˜๊ณ  ๋Œ€์‹  ๊ทธ๋ฃน์„ ์ง€์ •ํ•  ๋•Œ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ ์ˆ˜์ค€ ์ฃผ์„์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. ๊ทธ๋Ÿฌ๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

ํƒ€์ž„์Šคํƒฌํ”„์™€ ๊ด€๋ จํ•˜์—ฌ.. ์ด๊ฒƒ์„ ํ™•์ธํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ ๋‹ค๋ฅธ ๋ชจ๋“  ๋ฐฉ๋ฒ•์„ ์ œ๊ฑฐํ•˜๊ณ  ๋‘ ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•์„ ๊ฐ€์ง€๊ณ  ๋‹ค์‹œ ํ•œ ๋ฒˆ ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. TestNG๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ExecutorService ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์‹œ์„ฑ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. AFAIK๊ฐ€ ExecutorService ์ž‘์—…์„ ์ œ์ถœํ•œ๋‹ค๊ณ  ํ•ด์„œ ์ฆ‰์‹œ ์‹คํ–‰๋œ๋‹ค๋Š” ์˜๋ฏธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฑฐ๊ธฐ์—์„œ ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ด ๋ณ„๋กœ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ…Œ์ŠคํŠธ๋Š” ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋™์ผํ•œ ์Šค๋ ˆ๋“œ ID๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์ด์ œ ์ด์ƒํ•œ ํ–‰๋™์—..
๊ท€ํ•˜์˜ ๊ฒฝ์šฐ a ๋ฐ b ๋‘ ๊ทธ๋ฃน์„ ํฌํ•จํ•˜๊ณ  ๋‘ ๊ฐœ์˜ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ๋Œ€ํ•ด TestNG๋Š” ๊ธฐ๋ณธ ํด๋ž˜์Šค์—์„œ @BeforeClass ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ์‹คํ–‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์„ ํƒ ๋‹จ์œ„๊ฐ€ "๊ทธ๋ฃน"์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. TestNG๋Š” ๊ทธ๋ฃน์„ ์‚ฌ์šฉํ•˜์—ฌ "์‹คํ–‰ ๋Œ€์ƒ"์„ ์ฐพ์Šต๋‹ˆ๋‹ค. ์ผ๋‹จ ๊ฒฐ์ •๋˜๋ฉด ๊ทธ๋ฃน์€ ๊ด€๋ จ์„ฑ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ํด๋ž˜์Šค์—๋Š” @BeforeClass ์ˆ˜์ค€์—์„œ "๋‘" ๊ตฌ์„ฑ ๋ฐฉ๋ฒ•์ด ์žˆ์œผ๋ฏ€๋กœ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ๋Œ€ํ•ด ๋‘˜ ๋‹ค ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๊ทธ ์ž์ฒด๋กœ ๋ฌธ์ œ๋กœ ๋ณด์ง€ ์•Š๋Š”๋‹ค.

๋˜ํ•œ ๋ณ‘๋ ฌ ์‹คํ–‰์€ Test ๋ฉ”์„œ๋“œ์™€ NOT CONFIGURATION ๋ฉ”์„œ๋“œ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ์ˆ˜์ •ํ•ด์•ผ ํ•  ๋ณด๋ฅ˜ ์ค‘์ธ ์œ ์ผํ•œ ๊ฒƒ์€ ํด๋ž˜์Šค ์ˆ˜์ค€ ๋ฐ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ ์ˆ˜์ค€์— ๊ทธ๋ฃน์ด ํฌํ•จ๋  ๋•Œ ๊ทธ๋ฃน ์„ ํƒ์ด ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋  ๋•Œ ๋ฌด์–ธ๊ฐ€๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

_๋‚˜ ์ž์‹ ์— ๋Œ€ํ•œ ์ฐธ๊ณ  ์‚ฌํ•ญ_ : https://github.com/cbeust/testng/pull/1992 ์ฃผ๋ณ€์˜ ๋ฌด์–ธ๊ฐ€์™€ ๊ด€๋ จ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์žฌํ˜„ํ•  ์ƒ˜ํ”Œ

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class BaseTest {
  public static List<String> logs = new ArrayList<>();

  @BeforeClass(groups = {"a"})
  public void beforeClassA() {
    printer();
  }

  @BeforeClass(groups = {"b"})
  public void beforeClassB() {
    printer();
  }

  @AfterClass(groups = {"a"})
  public void afterClassA() {
    printer();
  }

  @AfterClass(groups = {"b"})
  public void afterClassB() {
    printer();
  }

  void printer() {
    ITestResult result = Reporter.getCurrentTestResult();
    String className = "";
    String methodName = result.getMethod().getMethodName();
    Method m = result.getMethod().getConstructorOrMethod().getMethod();
    String annotation = "";
    String groups = "";
    BeforeClass beforeClass = m.getAnnotation(BeforeClass.class);
    if (beforeClass != null) {
      annotation = "@BeforeClass";
      groups = Arrays.toString(beforeClass.groups());
    }
    AfterClass afterClass = m.getAnnotation(AfterClass.class);
    if (afterClass != null) {
      annotation = "@AfterClass";
      groups = Arrays.toString(afterClass.groups());
    }
    Test test = m.getAnnotation(Test.class);
    if (test != null) {
      annotation = "@Test";
      groups = Arrays.toString(test.groups());
    }
    String tid = Long.toString(Thread.currentThread().getId());
    String instanceId = result.getInstance().toString();
    String msg =
        String.format(
            "Running %s annotated %s.%s() [ belongs to groups %s] on Thread [%s] aind instanceId = %s",
            annotation, className, methodName, groups, tid, instanceId);
    System.err.println(msg);
    log(msg);
  }

  private static synchronized void log(String msg) {
    logs.add(msg);
  }
}
import org.testng.annotations.Test;

@Test(groups = "a")
public class ClassA extends BaseTest {
  <strong i="5">@Test</strong>
//  @Test(groups = "a")
  public void someTest() {
    printer();
  }
}
import org.testng.annotations.Test;

@Test(groups = "b")
public class ClassB extends BaseTest {
  <strong i="8">@Test</strong>
//  @Test(groups = "b")
  public void someTest() {
    printer();
  }
}
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.testng.Assert;
import org.testng.TestNG;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlGroups;
import org.testng.xml.XmlRun;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlSuite.ParallelMode;
import org.testng.xml.XmlTest;

public class TestRunner {
  public static void main(String[] args) {
    XmlSuite xmlSuite = new XmlSuite();
    xmlSuite.setName("test_suite");
    XmlTest xmlTest = new XmlTest(xmlSuite);
    xmlTest.setName("sample_test");
    XmlGroups xmlGroups = new XmlGroups();
    XmlRun xmlRun = new XmlRun();
    xmlRun.onInclude("a");
    xmlRun.onInclude("b");
    xmlGroups.setRun(xmlRun);
    xmlTest.setGroups(xmlGroups);
    List<XmlClass> xmlClasses =
        Arrays.asList(new XmlClass(ClassA.class), new XmlClass(ClassB.class));
    xmlTest.setXmlClasses(xmlClasses);
    xmlSuite.setParallel(ParallelMode.CLASSES);
    xmlSuite.setThreadCount(2);
    xmlSuite.setVerbose(2);
    TestNG testng = new TestNG();
    testng.setXmlSuites(Collections.singletonList(xmlSuite));
    testng.run();
    System.err.println(BaseTest.logs.size());
    Assert.assertEquals(BaseTest.logs.size(), 10);
  }
}

๊ธฐ๋ณธ ํด๋ž˜์Šค์—๋Š” @BeforeClass ์ˆ˜์ค€์—์„œ "๋‘" ๊ตฌ์„ฑ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ๋Œ€ํ•ด ๋‘˜ ๋‹ค ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๊ทธ ์ž์ฒด๋กœ ๋ฌธ์ œ๋กœ ๋ณด์ง€ ์•Š๋Š”๋‹ค.

๋‘ ๊ฐ€์ง€ ๊ตฌ์„ฑ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ ๋‹ค๋ฅธ ๊ทธ๋ฃน์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ๊ทธ๋ฃน ๋ชฉ์  ์ค‘ ํ•˜๋‚˜๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ทธ๋ฃน๊ณผ ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ์„ค์ • ๋ฐ ํ•ด์ œ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. :/

@MindaugasMateika

๋‘ ๊ฐ€์ง€ ๊ตฌ์„ฑ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ ๋‹ค๋ฅธ ๊ทธ๋ฃน์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ๊ทธ๋ฃน ๋ชฉ์  ์ค‘ ํ•˜๋‚˜๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ทธ๋ฃน๊ณผ ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ์„ค์ • ๋ฐ ํ•ด์ œ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์˜ˆ. ๊ทธ๋Ÿฌ๋‚˜ ์‹คํ–‰์— ํฌํ•จํ•  ๋‘ ๊ทธ๋ฃน์„ ๋ชจ๋‘ ์„ ํƒํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

@juherr @cbeust WDYT?

์˜ˆ, ๋‘ ๊ทธ๋ฃน ๋ชจ๋‘์—์„œ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์ง€๋งŒ ๊ตฌ์„ฑ ๋ฐฉ๋ฒ• ์‹คํ–‰์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ๊ทธ๋ฃน์„ ๋ชจ๋‘ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์—ฌ์ „ํžˆ ์ด ๊ฒฝ์šฐ ๊ทธ๋ฃน์ด ์žˆ๋Š” ์ „/ํ›„ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•ด๋‹น ๊ทธ๋ฃน๊ณผ ํ•จ๊ป˜ ์ˆ˜์—… ์ „/ํ›„์— ์‹คํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ยฏ_(ใƒ„)_/ยฏ

@MindaugasMateika - ์„ค๋ช…์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์ตœ์„ ์„ ๋‹คํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‹น์‹ ์ด ํ™•์‹ ํ•˜์ง€ ๋ชปํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•œ๋ฐœ์ง ๋ฌผ๋Ÿฌ์„œ์„œ @cbeust ๋‚˜ @juherr ๊ฐ€ ๋‹น์‹ ์—๊ฒŒ ๋‹ต์„ ์ค„ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ ๊ฒ ์Šต๋‹ˆ๋‹ค .

https://github.com/cbeust/testng/issues/2135#issuecomment -524169438๊ณผ ๊ด€๋ จ๋œ ๋ฌธ์ œ๋Š” ํด๋ž˜์Šค ์ˆ˜์ค€์—์„œ @Test ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ทธ๋ฃน ์ •๋ณด๋ฅผ ํฌํ•จํ•  ๋•Œ ๊ตฌ์„ฑํ•œ ๋‹ค์Œ ๋ฉ”์„œ๋“œ๋Š” ๊ฒฐ๊ตญ ๊ทธ๋ฃน๋„ ์ƒ์†ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด TestNG์˜ ๋™์ž‘์ž…๋‹ˆ๋‹ค.

@BeforeXXX ๊ตฌ์„ฑ ์ฃผ์„์„ ํ†ตํ•ด inheritGroups=false ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์šฐ๋ฆฌ๋Š” TestNG์˜ ๋™์ž‘์„ ๋ณ€๊ฒฝํ•˜์—ฌ ํด๋ž˜์Šค ์ˆ˜์ค€ @Test ์ฃผ์„์—์„œ ๊ตฌ์„ฑ ์ฃผ์„์œผ๋กœ ๊ทธ๋ฃน ์ •๋ณด๋ฅผ ์ƒ์†ํ•˜๋Š” TestNG์˜ ๋™์ž‘์ด <groups> ๋ฅผ ํ†ตํ•ด ๊ทธ๋ฃน ํ•„ํ„ฐ๋ง์ด ์„ ํƒ๋œ ๊ฒฝ์šฐ์—๋งŒ ์ผœ์ง€๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. https://github.com/cbeust/testng/pull/2167์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค.

@juherr @cbeust - ์ด ๋ฌธ์ œ์—์„œ ๋ชจ๋“  ๋ฏธํ•ด๊ฒฐ ์ฟผ๋ฆฌ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ณด๋ฅ˜์ค‘์ธ ์œ ์ผํ•œ ๊ฒƒ์€ ๋‹น์‹  ์ค‘ ํ•œ ๋ช…์ด ์ฐจ์ž„๋ฒจ์„ ์šธ๋ฆฌ๊ณ  @MindaugasMateika ์งˆ๋ฌธ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค (์–ด๋–ค ์ด์œ ๋กœ ๋‚ด ์„ค๋ช…์ด ๋งŒ์กฑ์Šค๋Ÿฝ์ง€ ์•Š์€ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค)

์ฝ”๋“œ ๊ด€์ ์—์„œ ์ด ๋ฌธ์ œ์—์„œ ํ•ด๊ฒฐํ•ด์•ผ ํ•  ๋‹ค๋ฅธ ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค.

@krmahadevan naah, ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ์œ ์ผํ•œ ์‚ฌ๋žŒ์ด๊ณ  ์—ฌ๊ธฐ์—์„œ ๋ชจ๋“  ๊ฒƒ์ด ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•œ๋‹ค๋ฉด ์Šค์Šค๋กœ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ซ์„ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์š” ๐Ÿ”

์œ„์˜ ์˜๊ฒฌ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๊ฒƒ์„ ๋‹ซ์Šต๋‹ˆ๋‹ค.

@Proryanator ์„ค๋ช…์„ ์ƒ˜ํ”Œ๋กœ ๋ฒˆ์—ญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฆ‰:

@BeforeMethod๊ฐ€ ์ •์˜๋œ 'BaseTest' ํด๋ž˜์Šค๊ฐ€ ์žˆ๊ณ  @test ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด ์ค‘์š”ํ•œ ๋ฐฉ๋ฒ•์ด ์‹คํŒจํ•  ๊ฒฝ์šฐ @BeforeMethod ์‹คํ–‰์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋‹จ์ง€ @BeforeMethod ๋ฅผ extendsOnMethods = {"importantParentBeforeMethod"}์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

public abstract class BaseTest {

  @BeforeMethod(dependsOnMethods = {"importantParentBeforeMethod"})
  public void setUp() {
    ...
  }
}

@Proryanator ์„ค๋ช…์„ ์ƒ˜ํ”Œ๋กœ ๋ฒˆ์—ญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฆ‰:

@BeforeMethod๊ฐ€ ์ •์˜๋œ 'BaseTest' ํด๋ž˜์Šค๊ฐ€ ์žˆ๊ณ  @test ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด ์ค‘์š”ํ•œ ๋ฐฉ๋ฒ•์ด ์‹คํŒจํ•  ๊ฒฝ์šฐ @BeforeMethod ์‹คํ–‰์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋‹จ์ง€ @BeforeMethod ๋ฅผ extendsOnMethods = {"importantParentBeforeMethod"}์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

public abstract class BaseTest {

  @BeforeMethod(dependsOnMethods = {"importantParentBeforeMethod"})
  public void setUp() {
    ...
  }
}

ํ• ๊นŒ๋ง๊นŒ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ํ—คํ—ค ๋ฌธ์ œ์—†์–ด์š”!

์ €๋Š” ์ง€๊ธˆ TestNG 7.0.0์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ €๋Š” ์ฃผ๋กœ _group_์— ์ƒ๊ด€์—†์ด

๋”ฐ๋ผ์„œ ๋ชจ๋ฐ”์ผ ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์„ค์ •ํ•˜๋Š” ์ตœ์ƒ์œ„ ์ƒ์œ„ ํด๋ž˜์Šค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์–ด์„ค์…˜์ด ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

public abstract class AbstractMobileBaseTest{
   @BeforeMethod(alwaysRun = true)
   public void mobileDriverCreation(){
      if (couldNotCreateDriver()){
         Assert.fail("Could not create the driver at all...");
      }
   }
}

๋ชจ๋“  ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๊ฐ€ ์ƒ์†ํ•˜๋Š” ์ž์‹ ํด๋ž˜์Šค๋กœ, ๊ทธ๋ฃน์— ๊ด€๊ณ„์—†์ด ํ•ญ์ƒ 'createSharedObjects'๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•˜์ง€๋งŒ ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํŒจํ•˜๋ฉด ์‹คํ–‰๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

public abstract class MobileAppBaseTest extends AbstractMobileBaseTest{
   @BeforeMethod(alwaysRun = true, dependsOnMethods = {"mobileDriverCreation"})
   public void makeMostPages(){
      // does some setup stuff here
   }
}

์—ฌ๊ธฐ์— ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜์ง€ ์•Š์€ ํ•˜์œ„ ํด๋ž˜์Šค์—๋„ ๋‹ค๋ฅธ __@BeforeMethods_ ๊ฐ€ ์žˆ์ง€๋งŒ _alwaysRun = true_ ๋ฐ _dependsOnMethods = {"mobileDriverCreation"}_์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ ์‹คํ–‰๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•.

๋‚˜๋Š” ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ์ง€๊ธˆ ๋‹จ ํ•˜๋‚˜์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

mvn verify ... -Dit.test=TestClassName -Dgroups=groupName

๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ญ”๊ฐ€ mobileDriverCreation ()์— ์ž˜๋ชป๋˜๋ฉด ๋‚ด๊ฐ€ ์‹คํ–‰ํ•˜์ง€์— ์ž์‹ @BeforeMethods๋Š”, ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ๋‹ค์Œ์„ ์ฐธ์กฐ ๊ธฐ๋Œ€ @BeforeMethod :

Screen Shot 2020-12-30 at 15 02 11

mobileDriverCreation()์— ์–ด์„ค์…˜ ์‹คํŒจ๊ฐ€ ์žˆ์ง€๋งŒ ๋‹ค๋ฅธ ๋ชจ๋“  @BeforeMethods๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค(์ž์‹ ์˜ ์˜ˆ์™ธ ๋ฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์ฒซ ๋ฒˆ์งธ ๋ฉ”์„œ๋“œ์—

๋‚˜๋Š” ํ›„์† ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ–ˆ๋Š”๋ฐ, _makeMostPages_ ๋ฐ _digitalServicesMobileSetup_ ์ด๋ผ๋Š” ํ•˜์œ„

Screen Shot 2020-12-30 at 16 46 28

_alwaysRun = true_๊ฐ€ _dependsOnMethods_๋ณด๋‹ค ์šฐ์„ ํ•˜๋ฉฐ ๊ฑฐ์˜ ๋ฌด์‹œํ•˜๊ฑฐ๋‚˜ ๋งˆ์ง€๋ง‰์œผ๋กœ ํ™œ์šฉ/ํ™•์ธ๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋‚˜์ค‘ ๋‹จ๊ณ„๋กœ _dependsOnMethods_๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ €๋Š” _groups_๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•œ _dependsOnMethods_๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ _groups_๋ฅผ ์ •๊ธฐ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค ๐Ÿ˜„

@juherr @krmahadevan

์ฒ ์ €ํ•˜๊ฒŒ ๋งํ•˜์ž๋ฉด, ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ๋Š” ์Šค์œ„ํŠธ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด maven-failsafe-plugin์—์„œ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ Include๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ _**.java_์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด _alwaysRun = true_ ๋ฐ _dependsOnMethods_๊ฐ€ ํ•ด์„๋˜๋Š” ๋ฐฉ์‹์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ:

์„ ์‚ฌ์šฉํ•ด ์ฃผ์‚ฌ๋ฅผ ์‹œ๋„ํ•˜๊ธฐ๋„ ํ–ˆ์Šต๋‹ˆ๋‹ค.ํƒœ๊ทธ๋ฅผ ์ง€์ •ํ•˜๊ณ  ๋ช…๋ น์ค„์„ ํ†ตํ•ด ์ „๋‹ฌํ•˜์ง€ ์•Š์ง€๋งŒ ์—ฌ์ „ํžˆ ์œ„์˜ ๋™์ž‘์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>${failsafe.plugin.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
            <configuration>
              <!-- This reads in any other system variables that you provide via -DparamName=value -->
              <systemPropertyVariables>
                <mobile>${mobile}</mobile>
                <url>${url}</url>
                <platform>${platform}</platform>
                <remote>${remote}</remote>
                <!-- Thread count is set by default variable at the top, if you'd like to change it pass in 'threadCount' as a system variable -->
                <threadCount>${threadCount}</threadCount>
                <retryCount>${retryCount}</retryCount>
                <iosVersion>${iosVersion}</iosVersion>
              </systemPropertyVariables>
              <argLine>
                -javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
              </argLine>
              <!-- Cannot run parallel using methods yet, use classes -->
              <parallel>classes</parallel>
              <threadCount>${threadCount}</threadCount>
              <skip>false</skip>
              <encoding>${project.build.sourceEncoding}</encoding>
              <includes>
                <include>${include}</include>
              </includes>
              <workingDirectory>target/${mobile}</workingDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>

@Proryanator - TestNG 7.3.0 ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฒจ๋ถ€๋œ ์ƒ˜ํ”Œ์„ ์ด์šฉํ•ด๋ณด์„ธ์š”.

issue_2135.zip

์ƒ˜ํ”Œ์ด ๋‹น์‹ ์ด ์‹œ๋„ํ•œ ๊ฒƒ๊ณผ ๋‹ค๋ฅด๊ณ  ๋‚ด๊ฐ€ ๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ƒ˜ํ”Œ์„ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ž์œ ๋กญ๊ฒŒ ์ƒˆ ํ˜ธ๋ฅผ ์—ด๊ณ  ์ƒ˜ํ”Œ์„ ์ฒจ๋ถ€ํ•˜์‹ญ์‹œ์˜ค.

@krmahadevan ์ƒ˜ํ”Œ์—์„œ ๊ณฐ ๋น„์œ ๊ฐ€ ์ข‹์•„์š” ๐Ÿ˜†

์ƒ˜ํ”Œ์„ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์•ฝ๊ฐ„์˜ ์ˆ˜์ •์„ ๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‹คํŒจํ•  ๋•Œ๋ฅผ ์šฐ๋ คํ•˜๊ธฐ ๋•Œ๋ฌธ์— 'GrandpaBear' @BeforeMethod ๋ฅผ ์ข€ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ•ญ์ƒ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ์ตœ์ƒ์œ„ ๋ถ€๋ชจ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

public class GrandpaBearGitHubTest {
  @BeforeMethod(alwaysRun = true)
  public void mobileDriverCreation() {
    Assert.fail("Could not create the driver at all...");
  }
}

์ด์ œ ์ด @BeforeMethod ๋Š” ํ•ญ์ƒ ์–ด์„ค์…˜ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์ด ํด๋ž˜์Šค ์•„๋ž˜์˜ ์ฒซ ๋ฒˆ์งธ ํด๋ž˜์Šค๋Š” _alwaysRun=true_ ๋ฐ _dependsOnMethods_๋กœ, _mobileDriverCreation_ ์ด๋ผ๋Š” @BeforeMethod๊ฐ€ ์‹คํŒจํ•˜๋ฉด ์‹คํ–‰๋˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

public class PapaBearGithubTest extends GrandpaBearGitHubTest {

  @BeforeMethod(alwaysRun = true, dependsOnMethods = {"mobileDriverCreation"})
  public void makeMostPages() {
    System.out.println("Ran makeMostPages");
  }
}

๋‹ค์Œ์€ ๊ฐ„๋‹จํ•œ @Test ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

public class GrandsonBearGithubTest extends PapaBearGithubTest {

  @Test(groups = "yogi-bear")
  public void testMethod() {
    System.err.println("Running test method");
  }
}

๋‹ค์Œ์€ -Dgroups=yogi-bear๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ ๋ชจ๋‘ ์ž์‹ ํด๋ž˜์Šค @BeforeMethod๊ฐ€ ์—ฌ์ „ํžˆ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค('Ran makeMostPages'๋ฅผ ์ธ์‡„ํ•  ๋•Œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์ข…์†๋œ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํŒจํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ :

[-Dgroup์œผ๋กœ ์‹คํ–‰]
Screen Shot 2020-12-31 at 09 14 01
[-Dgroup ์—†์ด ์‹คํ–‰]
Screen Shot 2020-12-31 at 09 14 14

๋˜ํ•œ IntelliJ์—์„œ ์‹คํ–‰ํ•˜์—ฌ maven์ด ๊ทธ๋ฃน์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด ์•„๋‹ˆ๋ผ TestNG์— ๋Œ€ํ•œ ๊ฒƒ์ธ์ง€ ํ™•์ธํ–ˆ์ง€๋งŒ ๊ฒฐ๊ณผ๋Š” ๋™์ผํ–ˆ์Šต๋‹ˆ๋‹ค.
Screen Shot 2020-12-31 at 09 15 26

๋‚ด ์ƒ๊ฐ์— _alwaysRun=true_๋Š” ๋‹จ๋ฝ์„ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๊ฑฐ๋‚˜ ์„œ๋กœ ํ•จ๊ป˜ ์ž‘๋™ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” _dependsOnMethods_๋ณด๋‹ค ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋†’์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ํƒ์ƒ‰/ํ…Œ์ŠคํŠธ์—์„œ ๋‘ ๋ฒˆ์งธ @BeforeMethod ๋ฅผ @BeforeMethod ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์•˜์œผ๋ฉฐ ์ด๋Š” ๋™์ž‘ ๋ฌธ์ œ๊ฐ€ _alwaysRun=true_๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ํšŒ์ „ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ด์ œ ์˜ˆ์ƒ๋˜๋Š” -Dgroups=yogi-bear๋ฅผ ์ง€์ •ํ•  ๋•Œ๋งŒ ์ด @BeforeMethod๋ฅผ ์‹คํ–‰ํ•˜์ง€๋งŒ _dependsOnMethods_๋ฅผ ์กด์ค‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด์ œ ์ƒˆ๋กœ์šด

public class PapaBearGithubTest extends GrandpaBearGitHubTest {

  @BeforeMethod(alwaysRun = true, dependsOnMethods = {"mobileDriverCreation"})
  public void makeMostPages() {
    System.out.println("Ran makeMostPages");
  }

  @BeforeMethod(groups = {"yogi-bear"}, dependsOnMethods = {"mobileDriverCreation"})
  public void makeOtherPages() {
    System.out.println("Ran makeOtherPages");
  }
}

์ƒˆ๋กœ์šด @BeforeMethod ๊ฐ€ ์‹คํ–‰๋˜์—ˆ์„ ๊ฒฝ์šฐ 'Ran makeOtherPages'๊ฐ€ ํ‘œ์‹œ๋˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ์ถœ๋ ฅ์€ ํ‘œ์‹œ๋˜์ง€ ์•Š๊ณ  ์ฒซ ๋ฒˆ์งธ ํ•ญ๋ชฉ์˜ 'Ran makeMostPages'๋งŒ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
Screen Shot 2020-12-31 at 09 26 32

@krmahadevan ์—…๋ฐ์ดํŠธ๋œ ์ƒ˜ํ”Œ์„ ์ฒจ๋ถ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋ฌธ์ œ๋ฅผ ์—ด์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
์—…๋ฐ์ดํŠธ๋œ-issue_2135.zip

์ˆ˜์ • ์ž‘์—…์— ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ์กฐ์ง์—์„œ ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ @BeforeMethod ์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ๋ถ„์„๋˜๋Š” ๋ฐฉ๋ฒ•์— ๊ด€ํ•ด์„œ๋Š” ์†Œ์Šค ์ฝ”๋“œ์—์„œ ์–ด๋””๋ฅผ ๋ด์•ผ ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉํ–ฅ ๐Ÿ˜„

@Proryanator ์ƒˆ ๋ฌธ์ œ๋ฅผ ์—ด โ€‹โ€‹์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ด ์˜ค๋ž˜๋œ ๋‹ซํžŒ ๋ฌธ์ œ๋ณด๋‹ค ๋‚˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค :)

@Proryanator ์ƒˆ ๋ฌธ์ œ๋ฅผ ์—ด โ€‹โ€‹์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ด ์˜ค๋ž˜๋œ ๋‹ซํžŒ ๋ฌธ์ œ๋ณด๋‹ค ๋‚˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค :)

์—ฌ๊ธฐ์—์„œ ์ƒˆ๋กœ ์—ด๋ฆฐ ๋ฌธ์ œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. #2448

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰