2015-10-27 3 views
10

Ok, так что у меня есть класс, как этотоднозначно идентифицировать каждый тестовый вызов в TestNG

public class Calculator { 

    @Test(dataProvider = "dp") 
    public void add(int a, int b) { 
     System.out.println("Invoked add: a, b" + a + "," + b); 
    } 

    @DataProvider(name = "dp") 
    public Object[][] createData(ITestContext ctx) { 
     return new Object[][] { new Object[] { 1, 2 }, new Object[] { 2, 3 } }; 
    } 

Когда тест выполняется, она будет работать добавить метод дважды. Я хочу отслеживать каждый вызов, добавляемый уникально на основе его ввода. Так сказать, add вызывается с 1,2 в качестве ввода, тогда это уникальный вызов. Если это не удается, я хочу сохранить эту информацию в базе данных с идентификатором вызова.

Как достичь этого с помощью testng? Все слушатели (methodinvocationlistener и т. Д.), Похоже, не предоставляют контекст, который однозначно идентифицирует прогон метода. Да, они позволяют вам видеть параметры, но я не могу отслеживать отдельные параметры. Итак, каким-то образом я ввожу свой собственный уникальный параметр в объект результата и отслеживаю его там?

UPDATE

Я добавляю улучшенный код, чтобы помочь лучше понять контекст. Это мой testng.xml

<suite name="Default Suite"> 
    <test name="test"> 
    <classes> 
     <class name="com.test.testng.Calculator"> 
     <methods> 
      <include name="add"> 
      <parameter name="data-id" value="1"/> 
      </include> <!-- add --> 
      <include name="add"> 
      <parameter name="data-id" value="2"/> 
      </include> <!-- add --> 
      <include name="subtract"> 
      <parameter name="data-id" value="3"/> 
      </include> <!-- subtract --> 
     </methods> 
     </class> <!-- com.test.testng.Calculator --> 
    </classes> 
    </test> <!-- test --> 
</suite> <!-- Default Suite --> 

У меня есть два инвокации дополнения и один вызов вычитать. Вот мой провайдер данных

public class Calculator { 

    @Test(dataProvider = "dp") 
    public void add(int first, int second) { 
     System.out.println("invoked add"); 
    } 

    @Test(dataProvider = "dp") 
    public void subtract(int first, int second) { 
     System.out.println("invoked subtract"); 
    } 

    @DataProvider(name = "dp") 
    public Object[][] createData(Method m, ITestContext ctx) {  
     Object[][] data = new Object[][] { new Object[] { 1, 2 }, new Object[] { 2, 3 }, new Object[] { 3, 4 } }; 
     for (XmlClass test : ctx.getCurrentXmlTest().getXmlClasses()) { 
      for (XmlInclude method : test.getIncludedMethods()) { 
       if (method.getName().equals(m.getName())) 
       int key = Integer.parseInt(method.getAllParameters().get("data-id")); 
       return new Object[][] { data[key - 1] }; 
      } 
     } 
     return null ; 
    } 

} 

Я ожидал, добавить бежать дважды, один раз с 1,2 в качестве входных данных, а другой раз с 2,3 в качестве входных данных. Аналогично, вычитайте с 3,4 в качестве входных данных. Но, что я видел это -

[SuiteRunner] Created 1 TestRunners 
[TestRunner] Running test test on 1 classes, included groups:[] excluded groups:[] 
===== Test class 
com.test.testng.Calculator 
    @Test Calculator.add(int, int)[pri:0, instance:[email protected]] 
    @Test Calculator.subtract(int, int)[pri:0, instance:[email protected]] 
====== 
method.getAllParamas(){data-id=1} 

[Invoker 665576141] Invoking com.test.testng.Calculator.add 
invoked 

[Invoker 665576141] Invoking com.test.testng.Calculator.subtract 
subtract 
===== Invoked methods 
    Calculator.add(int, int)[pri:0, instance:[email protected]]1 2 966808741 
    Calculator.subtract(int, int)[pri:0, instance:[email protected]]1 2 966808741 
===== 

мне нужно предоставить данные для каждого метода на основе специального параметра, который я собираюсь отправить с TestNG XML. Как мне это достичь?

+1

Что такое прецедент? Зачем вам/нужно сохранять состояние за пределами тестового сценария? –

+0

прецедент - это класс «Калькулятор» имеет 10 методов. Я хотел бы, чтобы пользователь выбирал, какие методы он хочет протестировать из пользовательского интерфейса, а затем для каждого метода, который он обозначил для тестирования, он будет загружать данные, относящиеся к каждому методу, через электронную таблицу. Данные таблицы сохраняются в базе данных и генерируется ключ. Во время выполнения, когда я генерирую testng xml, он будет содержать эти ключи, и DataProvider создаст входные данные после чтения сохраненных данных из базы данных. Теперь, как вы можете видеть, у меня разные вызовы, для тестов, все они динамически созданы. Мне нужно их отслеживать. – Jay

+0

Хорошо. В этом случае вы не можете сохранить UID/ключ для каждой записи в базе данных, прочитать это как часть DataProvider и передать UID в качестве параметра к методу тестирования? –

ответ

1

Для достижения этой цели вы можете определить Diferent случаев тесты в testng.xml, как это:

<suite name="Default Suite"> 
    <test name="test"> 
    <classes> 
     <class name="com.test.testng.Calculator"> 
     <methods> 
      <include name="add"> 
      <parameter name="data-id" value="1"/> 
      </include> <!-- add --> 
      <include name="subtract"> 
      <parameter name="data-id" value="3"/> 
      </include> <!-- subtract --> 
     </methods> 
     </class> <!-- com.test.testng.Calculator --> 
    </classes> 
    </test> <!-- test --> 
    <test name="test2"> 
    <classes> 
     <class name="com.test.testng.Calculator"> 
     <methods> 
      <include name="add"> 
      <parameter name="data-id" value="2"/> 
      </include> <!-- add --> 
     </methods> 
     </class> <!-- com.test.testng.Calculator --> 
    </classes> 
    </test> <!-- test --> 
</suite> <!-- Default Suite --> 

добавить журнал в методе поставщика:

package com.test.testng; 

import java.lang.reflect.Method; 

import org.testng.ITestContext; 
import org.testng.annotations.DataProvider; 
import org.testng.annotations.Test; 
import org.testng.xml.XmlClass; 
import org.testng.xml.XmlInclude; 

public class Calculator { 

    @Test(dataProvider = "dp") 
    public void add(int first, int second) { 
     System.out.println("invoked add"); 
    } 

    @Test(dataProvider = "dp") 
    public void subtract(int first, int second) { 
     System.out.println("invoked subtract"); 
    } 

    @DataProvider(name = "dp") 
    public Object[][] createData(Method m, ITestContext ctx) {  
     Object[][] data = new Object[][] { new Object[] { 1, 2 }, new Object[] { 2, 3 }, new Object[] { 3, 4 } }; 
     for (XmlClass test : ctx.getCurrentXmlTest().getXmlClasses()) { 
      for (XmlInclude method : test.getIncludedMethods()) { 

       if (method.getName().equals(m.getName())) { 
        int key = Integer.parseInt(method.getAllParameters().get("data-id")); 
        System.out.println("Running method " + m.getName() + " with data-id: " + key); 
        return new Object[][] { data[key - 1] }; 
       } 


      } 
     } 
     return null ; 
    } 

} 

Запуск этого XML как TestNG комплект (с плагином eclipse):

[TestNG] Running: 
    /Users/fhernandez/Documents/workspaceTest/testNg-test/src/test/resources/testng.xml 

Running method add with data-id: 1 
invoked add 
Running method subtract with data-id: 3 
invoked subtract 
Running method add with data-id: 2 
invoked add 

=============================================== 
Default Suite 
Total tests run: 3, Failures: 0, Skips: 0 
=============================================== 

Если я хорошо понимаю ваши требования, с этим вы можете Добейся этого.

Другим способом для достижения этого было бы поставить аспект или прокси-сервер перед тестовыми классами и провести проверку вызова метода, реализуя в этом аспекте/прокси ваши требования.

UPDATE

добавить прослушиватель в калькулятор с

@Listeners(Listener.class) 
public class Calculator 

слушатель выглядит следующим образом

package com.test.testng; 

import java.util.Arrays; 

import org.testng.IInvokedMethod; 
import org.testng.IInvokedMethodListener; 
import org.testng.ITestResult; 
import org.testng.xml.XmlClass; 
import org.testng.xml.XmlInclude; 

public class Listener implements IInvokedMethodListener { 

    public void afterInvocation(IInvokedMethod method, ITestResult itr) { 
     // TODO implements 
    } 

    public void beforeInvocation(IInvokedMethod method, ITestResult testResult) { 

     // Parameters value 
     System.out.println("Parameters invocation value for method " + method.getTestMethod().getMethodName()); 
     Arrays.asList(testResult.getParameters()).stream().forEach(System.out::println); 

     // get data-id 
     for (XmlClass test : testResult.getTestContext().getCurrentXmlTest().getXmlClasses()) { 
      for (XmlInclude met : test.getIncludedMethods()) { 

       if (met.getName().equals(method.getTestMethod().getMethodName())) { 
        int key = Integer.parseInt(met.getAllParameters().get("data-id")); 
        System.out.println("listener: Running method " + method.getTestMethod().getMethodName() + " with data-id: " + key); 
       }   
      } 
     } 
    } 
} 

Код в beforeInvocation показывают значения параметров Призыва и данных- id, это выход

[TestNG] Running: 
    /Users/fhernandez/Documents/workspaceTest/testNg-test/src/test/resources/testng.xml 

Running method add with data-id: 1 
Parameters invocation value for method add 
1 
2 
listener: Running method add with data-id: 1 
invoked add 
Running method subtract with data-id: 3 
Parameters invocation value for method subtract 
3 
4 
listener: Running method subtract with data-id: 3 
invoked subtract 
Running method add with data-id: 2 
Parameters invocation value for method add 
2 
3 
listener: Running method add with data-id: 2 
invoked add 

=============================================== 
Default Suite 
Total tests run: 3, Failures: 0, Skips: 0 
=============================================== 
+0

Спасибо, я делаю что-то подобное. Однако проблема заключается в отслеживании этих исполнений с использованием IInvokedMethodListener. На уровне слушателя нет доступа к этим параметрам. Здесь? – Jay

+0

Привет, я обновляю ответ whit слушателем, используя java 8 (для лямбда и потока).Я могу получить значения вызова параметров. Надежда помогает! –

+0

Я использую аналогичный подход к тому, что вы упомянули в ответе. Я не вижу другого способа доступа к идентификатору данных на уровне прослушивателя метода, кроме того, что все параметры (не примитивы) расширяют базовый класс и допускают только методы тестирования с минимальным одним параметром объекта java. Вы видите какой-либо другой способ доступа к идентификатору данных внутри метода beforeInvocation()? Я принимаю ваш ответ. – Jay

1

Первый аргумент в [] [] - количество проверок. Во-вторых, количество параметров. То есть
public Object [] [] createData (ITestContext ctx) { return new Object [] [] {новый объект [] {0,2}, новый объект [] {0,3} }; }


Будет ли запустить один тест с двумя параметрами 2,3.

1

Единичные испытания для разработчика , чтобы проверить собственный код, и никто другой.

Замечания к вопросу указывают «пользовательские параметры/тесты» в контексте, который помещает его в систему .

Не используйте модульное тестирование рамки для выполнения система испытания.

Важным моментом является то, что в предлагаемой среде возможно что-то внешний к коду (пользователь, добавляющий новые параметры теста), чтобы сломать сборку. Это плохо. Очень плохо. Если требуется новая функциональность, разработчик улучшит код и добавит новые тесты для его покрытия.

Взгляните на каркас BDDJBehave, который кажется более подходящим для вашей потребности.

+0

спасибо - это не для тестирования модулей/систем. Я создаю решение, которое использует testng для выполнения тестов. Таким образом, он нуждается в большой настройке. – Jay

Смежные вопросы