Java TestNG-工厂和数据提供商 背景故事

Java TestNG-工厂和数据提供商 背景故事,java,unit-testing,selenium,testng,webdriver,Java,Unit Testing,Selenium,Testng,Webdriver,我在一家软件公司工作,正在开发一个测试自动化框架,以取代我们的旧的意大利面条纠结系统 因为我们的系统几乎所有的操作都需要登录,所以我决定最好使用@BeforeMethod、@DataProvider和@Factory来设置测试。然而,我遇到了一些问题 样本测试用例 假设该软件系统是一个棒球队花名册。我们希望进行测试,以确保用户可以按姓名搜索团队成员 (注意:我知道before方法不会以任何给定的顺序运行——假设现在已经处理好了。) 本测试用例假设以下情况: 用户已登录(很可能使用BeforeM

我在一家软件公司工作,正在开发一个测试自动化框架,以取代我们的旧的意大利面条纠结系统

因为我们的系统几乎所有的操作都需要登录,所以我决定最好使用@BeforeMethod、@DataProvider和@Factory来设置测试。然而,我遇到了一些问题

样本测试用例 假设该软件系统是一个棒球队花名册。我们希望进行测试,以确保用户可以按姓名搜索团队成员

(注意:我知道before方法不会以任何给定的顺序运行——假设现在已经处理好了。)

本测试用例假设以下情况:

  • 用户已登录(很可能使用BeforeMethod)
  • 用户已导航到搜索页面(普通,在方法之前)
  • 测试的参数与上述登录关联
问题 因此,让我们试着找出如何处理测试用例的参数

创意#1

此方法允许我们将数据提供者与用户名关联,并允许我们对任何特定测试用例使用多个用户

@Test(dataProvider="players")
public void testSearch(String user, String pass, String name, String search) {
    // login with user/pass
    // acknowledge announcements
    // navigate to search page
    // ...
}
…但是有很多重复,因为我们必须让每个函数接受两个额外的参数。更不用说,我们还在测试acknowledge announcements特性,实际上我们并不想测试它

创意#2

因此,让我们使用工厂来正确初始化东西

class BaseTestCase {

    public BaseTestCase(String user, String password, Object[][] data);

}

class SomeTest {

    @Factory
    public void ...

}
这样,我们最终不得不为每个测试用例编写一个工厂。。。尽管如此,它确实允许我们在每个测试用例中有多个用户

结论 我几乎没有新的想法。我还有一个想法,就是从XML文件加载数据,然后从程序调用方法。。。但它越来越傻了


有什么想法吗?

首先,似乎您在每个测试用例中都做得太多了。例如,如果您正在搜索某物,为什么需要在搜索过程中测试导航

package example2;

import java.lang.reflect.Method;
import java.util.HashMap;
import org.testng.annotations.*;

public class WebTestBase {

  protected String host, username, password;
  protected HashMap<String, Object[][]> dataSet;

  public WebTestBase(String host, String username, String password, HashMap<String, Object[][]> dataSet) {
    this.host = host;
    this.username = username;
    this.password = password;
    this.dataSet = dataSet;
  }

  @DataProvider(name="dataSet")
  public Object[][] dataSet(Method m) {
    return dataSet.get(m.getName());
  }

  @BeforeMethod
  public void login() {
    System.out.println("Logging in to " + host + " with " + username + ":" + password);
  }

  @AfterMethod
  public void logout() {
    System.out.println("Logging out!");
  }
}
其次,您的要求似乎不明确。您能否创建一个测试,在其中发送单个搜索词并返回单个结果?看来这应该是你的第一次测试

第三,为什么授权会话连接/对象不能成为测试的要求?从代码的外观来看,您似乎正在通过HTTP进行某种调用。即使你不是,看起来你必须使用某种代理向你的应用程序发送消息,因为你必须传递用户名并传递每个请求。。。为什么不将整个过程自动化为一个“授权代理”对象,让您能够通过预先授权的连接发送请求


然后将授权代理传递到您的测试中,以处理您的消息传递。或者更好的方法是,在预测试(BeforeMethods?)函数中设置您的授权代理,并将其作为类成员变量提供。

我仍然不确定是否理解您的问题

您是否对第二次尝试不满意,即必须为每个测试用例编写@Factory?那么为什么不把@Factory注释放在基类构造函数上呢?这样,所有子类需要做的就是调用super,就完成了

你到底想达到什么目的?

塞德里克

我应该从第一天开始就做一个账户,我不能再编辑我的旧帖子,也不能回复评论(此时)。让我试着把事情扩大一点

这是我到目前为止提出的一个例子。我想我回答了我自己的问题。。。这是可行的,但有点恶心

我现在的问题是,我所有的测试都在一家工厂进行。这不好,有几个原因。第一,我必须手工添加它们(或将它们反射地放入)。第二,我必须把一切基本上都作为一个套件来运行。有什么想法吗

package example2;

import java.lang.reflect.Method;
import java.util.HashMap;
import org.testng.annotations.*;

public class WebTestBase {

  protected String host, username, password;
  protected HashMap<String, Object[][]> dataSet;

  public WebTestBase(String host, String username, String password, HashMap<String, Object[][]> dataSet) {
    this.host = host;
    this.username = username;
    this.password = password;
    this.dataSet = dataSet;
  }

  @DataProvider(name="dataSet")
  public Object[][] dataSet(Method m) {
    return dataSet.get(m.getName());
  }

  @BeforeMethod
  public void login() {
    System.out.println("Logging in to " + host + " with " + username + ":" + password);
  }

  @AfterMethod
  public void logout() {
    System.out.println("Logging out!");
  }
}
包示例2;
导入java.lang.reflect.Method;
导入java.util.HashMap;
导入org.testng.annotations.*;
公共类WebTestBase{
受保护的字符串主机、用户名、密码;
受保护的HashMap数据集;
公共WebTestBase(字符串主机、字符串用户名、字符串密码、HashMap数据集){
this.host=host;
this.username=用户名;
this.password=密码;
this.dataSet=数据集;
}
@数据提供者(name=“dataSet”)
公共对象[][]数据集(方法m){
返回dataSet.get(m.getName());
}
@预处理法
公共无效登录(){
System.out.println(“使用“+用户名+”:“+密码登录到“+主机+”);
}
@后置法
公开作废注销(){
System.out.println(“注销!”);
}
}

包示例2;
导入java.util.HashMap;
导入org.testng.annotations.Factory;
公共类WebTestFactory{
@工厂
公共对象[]工厂(){
HashMap dataSetOne=新的HashMap();
dataSetOne.put(“搜索花名册”,新对象[][]{
{“mcguire”,“mcguire,Mark”},
{“露丝”,“露丝,宝贝”}
});
HashMap DataSetwo=新HashMap();
datasetwo.put(“addPlayer”,新对象[][]{
{“萨米·索萨”,0.273}
});
对象[]测试=新对象[]{
新的搜索测试(“localhost”、“user”、“pass”、dataSetOne),
新的AddTest(“localhost”、“user”、“pass”、datasetwo)
};
回归测试;
}
}

包示例2;
导入java.util.HashMap;
导入org.testng.annotations.Test;
公共类SearchTest扩展WebTestBase{
公共搜索测试(字符串主机、字符串用户名、字符串密码、,
HashMap数据集){
超级(主机、用户名、密码、数据集);
}
@测试(dataProvider=“dataSet”)
公共无效搜索花名册(字符串搜索术语、字符串播放名称){
System.out.println(“搜索”+搜索词);
System.out.println(“我在搜索结果中找到了“+playerName+”);
}
}

包示例2;
导入java.util.HashMap;
导入org.testng.annotations.Test;
公共类AddTest扩展WebTestBase{
公共地址测试(字符串hos)
package example2;

import java.util.HashMap;

import org.testng.annotations.Factory;

public class WebTestFactory {
  @Factory
  public Object[] factory() {
    HashMap<String, Object[][]> dataSetOne = new HashMap<String, Object[][]>();
    dataSetOne.put("searchRoster", new Object[][] {
          {"mcguire", "McGuire, Mark"},
          {"ruth", "Ruth, Babe"}
        });

    HashMap<String, Object[][]> dataSetTwo = new HashMap<String, Object[][]>();
    dataSetTwo.put("addPlayer", new Object[][] {
          {"Sammy Sosa", 0.273}
        });

    Object[] tests = new Object[] { 
        new SearchTest("localhost", "user", "pass", dataSetOne),
        new AddTest("localhost", "user", "pass", dataSetTwo)
      };

    return tests;
  }
}
package example2;

import java.util.HashMap;
import org.testng.annotations.Test;

public class SearchTest extends WebTestBase {

  public SearchTest(String host, String username, String password,
      HashMap<String, Object[][]> dataSet) {
    super(host, username, password, dataSet);
  }

  @Test(dataProvider="dataSet")
  public void searchRoster(String searchTerm, String playerName) {
    System.out.println("Searching for " + searchTerm);
    System.out.println("I found " + playerName + " in the search results!");
  }

}
package example2;

import java.util.HashMap;

import org.testng.annotations.Test;

public class AddTest extends WebTestBase {

  public AddTest(String host, String username, String password,
      HashMap<String, Object[][]> dataSet) {
    super(host, username, password, dataSet);
  }

  @Test(dataProvider="dataSet")
  public void addPlayer(String playerName, double battingAvg) {
    System.out.println("Adding " + playerName + " with avg " + battingAvg);
  }
}