Testng: يتم إعادة تنفيذ عملياتTest من فئة super لكل فئة فرعية

تم إنشاؤها على ١٠ يونيو ٢٠١٩  ·  12تعليقات  ·  مصدر: cbeust/testng

إصدار TestNG 6.14.3

سلوك متوقع

يتم تنفيذ الطرق @Test من الفئة الممتازة مرة واحدة بغض النظر عن عدد الفئات الفرعية التي ترث الفئة الممتازة.

السلوك الفعلي

يتم تنفيذ الطرق @Test مع كل فئة فرعية.

هل المشكلة قابلة للظهور على العداء؟

  • [ ] صدفة
  • [] مخضرم
  • [x] جرادل
  • [] النملة
  • [ ] كسوف
  • [] IntelliJ
  • [] NetBeans

عينة حالة الاختبار

public class BaseTest  extends SetupClass{
    @BeforeClass...
    @BeforeMethod...
    @AfterClass...
    @AfterMethod....

    <strong i="22">@Test</strong>
    public void baseMethod(){
        System.out.println("base method");
    }
}
public class Test1 extends BaseTest{
    <strong i="25">@Test</strong>
    public void test1(){
        System.out.println("test1");
    }
}
public class Test2 extends BaseTest{
    <strong i="28">@Test</strong>
    public void test2(){
        System.out.println("test2");
    }
}

أقوم بإجراء هذه الاختبارات بالتوازي من ملف TestNG xml الذي يبدو كالتالي:

<suite name="Regression Suite" verbose="1" parallel="classes" thread-count="4">
    <parameter name="project" value="TestPrj"/>
    <parameter name="server" value="QA01"/>
    <test name="QA01 TestPrj">
        <parameter name="environment" value="macos"/>
        <groups>
            <run>
                <include name="regression"/>
            </run>
        </groups>
        <packages>
            <package name="test"/>
        </packages>
    </test>
</suite>

كود تحرير PS في مشكلات github سيء للغاية ... يرجى الانتقال إلى شيء آخر.

inheritance

ال 12 كومينتر

ههههههههههه

كود تحرير PS في مشكلات github سيء للغاية ... يرجى الانتقال إلى شيء آخر.

قد ترغب في قضاء بعض الوقت في التعرف على Markdown. سيجعل ذلك من السهل جدًا إضافة مقتطفات التعليمات البرمجية جنبًا إلى جنب مع التنسيق.

لست متأكدًا تمامًا من فهمي لمشكلتك هنا. في نهاية المطاف ، ستحصل الفصول الفرعية على طرق الفئة الأساسية أيضًا. وإذا تم شرحها بتعليقات TestNG التوضيحية ، فسيتم تنفيذها لكل فصل دراسي. هذا هو سلوك TestNG. لذلك أود أن أقول أن TestNG يعمل كما هو مصمم.

juherr - أفكارك؟

krmahadevan شكرا على التنسيق :)

لست متأكدًا تمامًا من فهمي لمشكلتك هنا. في نهاية المطاف ، ستحصل الفصول الفرعية على طرق الفئة الأساسية أيضًا. وإذا تم شرحها بتعليقات TestNG التوضيحية ، فسيتم تنفيذها لكل فصل دراسي. هذا هو سلوك TestNG. لذلك أود أن أقول أن TestNG يعمل كما هو مصمم.

إذا سألتني ، فلن يكون من المنطقي إجراء الاختبارات في فئة السوبر عدة مرات.
إذا كان هذا هو السلوك المتوقع لـ TestNG في الوقت الحالي ، فربما يمكننا إضافة هذا على أنه قيد التحسين.

تعمل حسب التصميم.
لماذا لا تنقل اختبار baseMethod في فئتها الخاصة؟

ههههههههههه

إذا سألتني ، فلن يكون من المنطقي إجراء الاختبارات في فئة السوبر عدة مرات.

ماذا تحاول انجازه بالضبط؟ سيكون من الرائع لو تفضلتم بالمساعدة في توضيح السيناريو الخاص بك أو شرحه.

إذا كان هذا هو السلوك المتوقع لـ TestNG في الوقت الحالي ، فربما يمكننا إضافة هذا على أنه قيد التحسين.

لست متأكدًا من أنه سيتم تناوله كتعزيز لأنه غير بديهي. إذا كنت تريد أساسًا تنفيذ طريقة الفئة الأساسية مرة واحدة تمامًا ، بغض النظر عن عدد الفئات الفرعية الموجودة ، فيمكنك القيام بذلك اليوم في مشروع الاختبار الخاص بك عن طريق القيام بما يلي

  1. اجعل صنفك الأساسي يطبق org.testng.IHookable
  2. ضمن طريقة run() ، أضف فحص تحرير للتحقق مما إذا كانت طريقة الفئة الأساسية قد تم تنفيذها بالفعل وتشغيلها إذا لم يتم تنفيذها.

هذه عينة

واجهة العلامة التي تشير إلى أنه يجب تشغيل طريقة الفئة الأساسية مرة واحدة فقط

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({METHOD, TYPE})
public <strong i="20">@interface</strong> RunOnce {
}

هذا هو واحد تعقب الدولة

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class StateTracker {

  private static final StateTracker instance = new StateTracker();

  private final Map<String, Object> runOnceData = new ConcurrentHashMap<>();

  private StateTracker() {}

  public static StateTracker getInstance() {
    return instance;
  }

  boolean canExecute(Method method) {
    RunOnce runOnce = method.getAnnotation(RunOnce.class);
    String methodName = method.getName();
    boolean execute = true;
    if (runOnce != null) {
      if (runOnceData.containsKey(methodName)) {
        execute = false;
      } else {
        runOnceData.put(methodName, new Object());
      }
    }
    return execute;
  }
}

إليك كيف ستبدو الفئة الأساسية

import org.testng.IHookCallBack;
import org.testng.IHookable;
import org.testng.ITestResult;
import org.testng.annotations.Test;

public class BaseTest implements IHookable {

  <strong i="27">@Test</strong>
  <strong i="28">@RunOnce</strong>
  public void baseclassTestMethod() {
    System.err.println("Base class test method executed");
  }

  <strong i="29">@Override</strong>
  public void run(IHookCallBack callBack, ITestResult testResult) {
    boolean execute =
        StateTracker.getInstance()
            .canExecute(testResult.getMethod().getConstructorOrMethod().getMethod());
    if (execute) {
      callBack.runTestMethod(testResult);
    } else {
      testResult.setStatus(ITestResult.SKIP);
      testResult.setThrowable(new RuntimeException("Intentionally skipping"));
    }
  }
}

إليك كيف ستبدو الفصول الفرعية

import org.testng.annotations.Test;

public class ChildClass1 extends BaseTest {

  <strong i="33">@Test</strong>
  public void childTest() {
    System.err.println(getClass().getName() + ".childTest() executed");
  }
}
import org.testng.annotations.Test;

public class ChildClass2 extends BaseTest {

  <strong i="36">@Test</strong>
  public void childTest() {
    System.err.println(getClass().getName() + ".childTest() executed");
  }
}

ستحتاج إلى إضافة بعض آلية التصفية التي تعمل على تقليم نتائج الاختبار وإزالة الاختبارات التي تم تخطيها والتي تم شرحها باستخدام @RunOnce

تضمين التغريدة
ماذا تحاول انجازه بالضبط؟ سيكون من الرائع لو تفضلتم بالمساعدة في توضيح السيناريو الخاص بك أو شرحه.

أحاول فصل الاختبارات في فئات متعددة (مرتبطة بميزة). على سبيل المثال لديك "الفئة الأساسية" الذي يحتوي على جزء الإعداد لهذه الميزة مع أساليبBefore وAfter على طول الطرق المساعد أخرى جانبية (وليس اختبارات) التي تدعم الاختبارات من الفئة الأساسية جنبا الى جنب مع الاختبارات في "الطبقات الطفل ". لذلك ، بهذه الطريقة ستضيف فقط اختبارات جديدة إلى فصول الأطفال ولا تكرر الكود في الفصول الفرعية.
سيكون للفئة الأساسية بعض طرق الاختبار التي تختبر أجزاء أكثر عمومية من تلك الميزة وستكون للفئات الفرعية اختبارات أكثر تحديدًا.
نظرًا لأنني أحاول تحسين وقت التشغيل التجريبي من خلال تشغيل الفصول الدراسية بالتوازي ، فقد اضطررت إلى تقسيم "الفئة الأساسية" الأصلية التي تضم أكثر من 50 طريقة اختبار إلى عدة "فئات فرعية" أصغر بحيث يتم توزيع هذه الفئات الأصغر على سلاسل عمليات أخرى / المنفذين.

krmahadevan شكرًا جزيلاً على الحل التفصيلي ولكنه يبدو مرهقًا بعض الشيء بالنسبة لي. نظرًا لأنه يمكن تخصيص TestNG ، فإنني أفضل أن أرى هذا السلوك الافتراضي.
لا أرى حاجة لإعادة تنفيذ الاختبارات باستمرار من الفئة الأساسية. إذا كان الأمر يتعلق بالإعداد / التمزيق ، فيمكن للمرء دائمًا استخدام @ Before / After ، فسيتم إعادة تنفيذه في كل مرة قبل فئة

نعم ، أعتقد أن السلوك يمكن أن يكون قابلاً للتكوين.

في الواقع ، لا أجد حالة استخدام حيث نريد إجراء اختبار الوالدين لكل مثيل طفل.
ما لم يكن لديك تبعية مباشرة للاختبار ( dependsOnMethods ) لأن حالة الاختبار غالبًا ما يتم تعديلها على هذا النحو في اختبارات التكامل.

krmahadevan WDYT؟

ههههههههههه

شكرًا جزيلاً على الحل التفصيلي ، لكنه يبدو مرهقًا بعض الشيء بالنسبة لي

تبدو حالة الاستخدام أيضًا مختلفة نوعًا ما عن العادية. علاوة على ذلك ، فقد أعطيتك مثالاً عمليًا عن كيفية القيام بذلك. كل ما عليك فعله هو تبني هذا والبناء عليه.

نظرًا لأنه يمكن تخصيص TestNG ، فإنني أفضل أن أرى هذا السلوك الافتراضي.

رقم لا يمكن أن يتم ذلك في رأيي. من المفترض أن يتم تنفيذ الاختبارات طوال الوقت. فقط لأنهم يقيمون في فئة أساسية لا يعني أنه يتعين عليهم التنفيذ بشكل انتقائي. يمكن تخصيص TestNG. لكن هذا لا يعني أن TestNG يحتاج إلى دعم جميع التخصيصات. إنه يحتاج فقط إلى توفير الطرق التي يجب أن يكون المستخدم قادرًا على تخصيصها لاحتياجاتهم والعمل معها. النموذج الذي قمت بمشاركته هو مثال على تطبيق تلك التخصيصات دون الحاجة إلى إجراء تغييرات على TestNG.

لا أرى حاجة لإعادة تنفيذ الاختبارات باستمرار من الفئة الأساسية. إذا كان الأمر يتعلق بالإعداد / التمزيق ، فيمكن للمرء دائمًا استخدام @ Before / after ، فسيتم إعادة تنفيذه في كل مرة قبل فئة

بالنسبة لي هذه مجرد طريقة واحدة للنظر إلى الأشياء. إذا لم يتم تنفيذ طريقة معينة في كل مرة ، فيجب ألا تستخدم التعليق التوضيحي @Test . يمكنك استخدام التعليقات التوضيحية للتكوين جيدًا مثل @BeforeTest (والتي يتم تنفيذها مرة واحدة فقط لكل علامة <test> ) أو @BeforeSuite (والتي يتم تنفيذها مرة واحدة فقط لكل <suite> tag) لا؟ ألن يعملوا من أجلك.

لست متأكدًا ، إذا كانت طرق الاختبار في فئتك الأساسية هي بالفعل طرق اختبار. بالنسبة لي ، تبدو أشبه بالتكوينات التي تحدد شروط الإعداد لتكون راضية عن الاختبار.

juherr - لست متأكدًا تمامًا من أنني أتفق مع حالة الاستخدام هنا. من المفترض أن يتم تنفيذ الاختبار بغض النظر عن مكان وجوده. إذا كان هناك سيناريو حيث لا نريد أن يتم تنفيذه لجميع الفئات الفرعية ، فيجب أن نستخدم التعليقات التوضيحية للتكوين وليس التعليق التوضيحي @Test .

من ناحية التنفيذ ، أعتقد أن هذا سيضيف الكثير من الفوضى إلى قاعدة التعليمات البرمجية خاصة عندما يبدأ الأشخاص في اللجوء إلى استخدام المجموعات كوسيلة للتنفيذ.

علاوة على ذلك ، أشعر أن هناك بالفعل طريقة للقيام بذلك حاليًا داخل TestNG (والتي قمت بمشاركتها كمثال). لماذا لا تكتفي بالاستفادة من ذلك؟ يبدو أن هذه حالة استخدام لمرة واحدة ، ولا يبدو أنها تتناسب مع الطريقة المعتادة لكيفية استخدام TestNG.

krmahadevan أنا آسف ، لكن أعتقد أنك لم تفهم ما أحاول القيام به.
في صفي الأساسي (BaseTest - على سبيل المثال DashboardTest) لدي 15 اختبارًا الآن ولدي 3 فصول فرعية (مثل DashboardFilterTest و DashboardTreeTest و DashboardEditorTest) التي تحتوي كل منها على اختبارات بالداخل. باستخدام النهج الذي وصفته في رسالتي ، في كل مرة أقوم فيها بإجراء الاختبارات ، يتم تنفيذ هذه الاختبارات الـ 15 ثلاث مرات (لذلك ، 3 × 15 = 45 اختبارًا قيد التنفيذ) لا تجلب أي قيمة وتمدد وقت التشغيل بلا فائدة ، بدلاً من مجرد تنفيذ 15 اختبارا مرة واحدة.

ما زلت أعتقد أنه ليس من المنطقي إعادة تنفيذ الاختبارات الموجودة في فصل دراسي أصلي في كل مرة يتم فيها تنفيذ اختبارات من فصل دراسي فرعي. يفضل السلوك الافتراضي لـ TestNG لتنفيذ طرق الاختبار من فئة رئيسية مرة واحدة ، بغض النظر عن عدد الفئات الفرعية التي تقوم بتوسيعها.

إذا كان هذا لا يمكن القيام به ، وأنا أفهم. شكرا على كل حال.

ههههههههههه

شكرا لإضافة سياق إضافي.

في صفي الأساسي (BaseTest - على سبيل المثال DashboardTest) لدي 15 اختبارًا الآن ولدي 3 فصول فرعية (مثل DashboardFilterTest و DashboardTreeTest و DashboardEditorTest) التي تحتوي كل منها على اختبارات بالداخل. باستخدام النهج الذي وصفته في رسالتي ، في كل مرة أقوم فيها بإجراء الاختبارات ، يتم تنفيذ هذه الاختبارات الـ 15 ثلاث مرات (لذلك ، 3 × 15 = 45 اختبارًا قيد التنفيذ) لا تجلب أي قيمة وتمدد وقت التشغيل بلا فائدة ، بدلاً من مجرد تنفيذ 15 اختبارا مرة واحدة.

في هذه الحالة ، لماذا يقوم DashboardFilterTest, DashboardTreeTest, DashboardEditorTest بتمديد DashboardTest ؟ يبدو أن الاختبارات DashboardTest تحتاج إلى الإقامة في فئتها الخاصة بدلاً من الاستفادة من نهج الميراث هنا ، أليس كذلك؟ يجب إعادة هيكلة الفئة الأساسية لإزالة جميع طرق الاختبار الشائعة وإدراجها في فئة اختبار منفصلة ، ويجب إعادة هيكلة DashboardTest لتضمين طرقًا عامة غير @Test أليس كذلك؟

إذا كان هذا لا يمكن القيام به ، وأنا أفهم. شكرا على كل حال.

لا يتعلق الأمر بما إذا كان من الممكن القيام بها أم لا (تحديات التنفيذ موضوع منفصل) ، لكن ما زلت أواجه صعوبة في محاولة فهم صحة حالة الاستخدام نفسها.

تضمين التغريدة

في هذه الحالة ، لماذا يقوم DashboardFilterTest, DashboardTreeTest, DashboardEditorTest بتمديد DashboardTest ؟ يبدو أن الاختبارات DashboardTest تحتاج إلى الإقامة في فئتها الخاصة بدلاً من الاستفادة من نهج الميراث هنا ، أليس كذلك؟ يجب إعادة هيكلة الفئة الأساسية لإزالة جميع طرق الاختبار الشائعة وإدراجها في فئة اختبار منفصلة ، ويجب إعادة هيكلة DashboardTest لتضمين طرقًا عامة غير @Test أليس كذلك؟

يحتوي "DashboardTest" على طرق مساعدة (مثل openDashboard () و createDashboard () وما إلى ذلك) وطرق setup / teardown / cleanup (@ Before / @ After) اللازمة للفئات الفرعية أيضًا. لذلك ، لست بحاجة إلى نسخ الكود في الفصول الفرعية.
نعم ، يمكن نقل بعض الاختبارات في "DashboardTest" إلى فئات أخرى محددة ولكني أردت الاحتفاظ بها هنا لأنها أكثر عمومية (على سبيل المثال ، التحقق من المظهر العام للوحة القيادة أو اختبارات CRUD الأساسية أو حتى بعض الاختبارات التي لم تفعل ذلك) تناسب فئة معينة أو مزيج).

بالتأكيد ، يمكنني الحصول على فئة اختبار بخلاف @ Test (على الرغم من أنه سيكون غريبًا ويمكن لأي شخص إضافة اختبارات هنا عن طريق الخطأ) ولكن سيكون فقط لتجنب هذه المشكلة ، أليس كذلك؟

ههههههههههه

يحتوي "DashboardTest" على طرق مساعدة (مثل openDashboard () و createDashboard () وما إلى ذلك) وطرق setup / teardown / cleanup (@ Before / @ after) اللازمة للفئات الفرعية أيضًا. لذلك ، لست بحاجة إلى نسخ الكود في الفصول الفرعية.

هذا يبدو منطقيا. ونعم ، يمكنهم الإقامة جيدًا داخل الفئة الأساسية بحيث يتم توفير طرق التكوين للفئات الفرعية أيضًا.

نعم ، يمكن نقل بعض الاختبارات في "DashboardTest" إلى فئات أخرى محددة ولكني أردت الاحتفاظ بها هنا لأنها أكثر عمومية (على سبيل المثال ، التحقق من المظهر العام للوحة القيادة أو اختبارات CRUD الأساسية أو حتى بعض الاختبارات التي لم تفعل ذلك) تناسب فئة معينة أو مزيج).

لا يزال بإمكانك إنشاء فئة تسمى GenericDashboardTest extends DashboardTest تضم جميع طرق @Test فيها.

بالتأكيد ، يمكنني الحصول على فئة اختبار غير @ (على الرغم من أنه سيكون غريبًا ويمكن لأي شخص إضافة اختبارات هنا عن طريق الخطأ) ولكن سيكون فقط لتجنب هذه المشكلة ، أليس كذلك؟

حسنًا ، أليس هذا هو ما يوجد من مراجعات الكود من أجل :) لمنع مثل هذه الانزلاقات. لا تحتاج الفئة الأساسية (مما أوضحته) إلى احتواء الطرق العامة العامة @Test . يمكن أن تستوعب بشكل جيد المساعدين والتكوينات فقط ويمكنك الحصول على فئة اختبار أخرى والتي تعمل على توسيع الفئة الأساسية وتضم طرق الاختبار العامة. يجب أن يحل هذا الالتباس في متناول اليد.

إغلاق هذه المشكلة بالقرار كـ _ العمل حسب التصميم_

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات