์์ ๋จ: 6.14.3
์ํผํด๋์ค์ @BeforeClass
๋ฐ @AfterClass
๋ ๊ทธ๋ฃน ๋งค๊ฐ๋ณ์๋ฅผ ์กด์คํด์ผ ํ๋ฉฐ ํด๋น ๊ทธ๋ฃน๊ณผ ํจ๊ป ํด๋์ค ์ ํ์ ์คํ๋์ด์ผ ํฉ๋๋ค.
6.14.3 @BeforeClass
๋ฐ @AfterClass
๋ ์์ ๊ทธ๋ฃน์ ๊ด๊ณ์์ด ๊ฐ ํด๋์ค์ ๋ํด ์คํ๋ฉ๋๋ค. ์๋ ์์ ํ
์คํธ ๋ฐ ์ถ๋ ฅ์ ์ฐธ์กฐํ์ญ์์ค. @BeforeClass
๋ฐ @AfterClass
๊ฐ ์ํผํด๋์ค ๋์ ๊ฐ ํ
์คํธ ํด๋์ค์ ์์ผ๋ฉด ์ ์๋ํ์ง๋ง ์ํผํด๋์ค๊ฐ ๋ชจ๋ ํ
์คํธ ํด๋์ค์ ๋ํ ์ค์ ๋ฐ ๋ถํด๋ฅผ ์ฒ๋ฆฌํ๋๋ก ํ๋ ๋ชฉ์ ์ ๋ฌดํจํ๋ฉ๋๋ค. ๊ฒ๋ค๊ฐ ์๋ง์ ์์ฉ๊ตฌ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
7.0.0์์ @BeforeClass and
@AfterClass` ํ
์คํธ ๋ฉ์๋ ์ ์ ๊ฐ ํด๋์ค์ ๋ํด ์ฌ๋ฌ ๋ฒ ์คํํฉ๋๋ค. ํ
์คํธ ๋ฉ์๋ ํ์๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค.
๊ทธ๋ฃน "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
์ค์ ๋ก ์์ ๋์์ 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 :
mobileDriverCreation()์ ์ด์ค์ ์คํจ๊ฐ ์์ง๋ง ๋ค๋ฅธ ๋ชจ๋ @BeforeMethods๊ฐ ์คํ๋ฉ๋๋ค(์์ ์ ์์ธ ๋ฐ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ ์ฒซ ๋ฒ์งธ ๋ฉ์๋์
๋๋ ํ์ ํ ์คํธ๋ฅผ ์ํํ๋๋ฐ, _makeMostPages_ ๋ฐ _digitalServicesMobileSetup_ ์ด๋ผ๋ ํ์
_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
์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ์ฌํํ ์ ์์ต๋๋ค. ์ฒจ๋ถ๋ ์ํ์ ์ด์ฉํด๋ณด์ธ์.
์ํ์ด ๋น์ ์ด ์๋ํ ๊ฒ๊ณผ ๋ค๋ฅด๊ณ ๋ด๊ฐ ๋ฌธ์ ๋ฅผ ์ฌํํ ์ ์๋๋ก ์ํ์ ์กฐ์ ํ ์ ์๋ค๋ฉด ์์ ๋กญ๊ฒ ์ ํธ๋ฅผ ์ด๊ณ ์ํ์ ์ฒจ๋ถํ์ญ์์ค.
@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์ผ๋ก ์คํ]
[-Dgroup ์์ด ์คํ]
๋ํ IntelliJ์์ ์คํํ์ฌ maven์ด ๊ทธ๋ฃน์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ด ์๋๋ผ TestNG์ ๋ํ ๊ฒ์ธ์ง ํ์ธํ์ง๋ง ๊ฒฐ๊ณผ๋ ๋์ผํ์ต๋๋ค.
๋ด ์๊ฐ์ _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'๋ง ํ์๋ฉ๋๋ค.
@krmahadevan ์
๋ฐ์ดํธ๋ ์ํ์ ์ฒจ๋ถํ์ต๋๋ค. ์ฌํํ ์ ์๋ค๋ฉด ๋ฌธ์ ๋ฅผ ์ด์ด๋ณด๊ฒ ์ต๋๋ค.
์
๋ฐ์ดํธ๋-issue_2135.zip
์์ ์์ ์ ์ ๊ฒฝ์ฐ์ง ์์ต๋๋ค. ์ฐ๋ฆฌ ์กฐ์ง์์ ์ด๊ฒ์ ์ฌ์ฉํ ์ ์์ง๋ง @BeforeMethod ์ ๋งค๊ฐ ๋ณ์๊ฐ ๋ถ์๋๋ ๋ฐฉ๋ฒ์ ๊ดํด์๋ ์์ค ์ฝ๋์์ ์ด๋๋ฅผ ๋ด์ผ ํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ฌ๋ฐ๋ฅธ ๋ฐฉํฅ ๐
@Proryanator ์ ๋ฌธ์ ๋ฅผ ์ด โโ์ ์์ต๋๊น? ์ด ์ค๋๋ ๋ซํ ๋ฌธ์ ๋ณด๋ค ๋์ ๊ฒ์ ๋๋ค :)
@Proryanator ์ ๋ฌธ์ ๋ฅผ ์ด โโ์ ์์ต๋๊น? ์ด ์ค๋๋ ๋ซํ ๋ฌธ์ ๋ณด๋ค ๋์ ๊ฒ์ ๋๋ค :)
์ฌ๊ธฐ์์ ์๋ก ์ด๋ฆฐ ๋ฌธ์ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. #2448