专栏首页Jerry的SAP技术分享Java反射机制在UI自动化测试中的一个应用

Java反射机制在UI自动化测试中的一个应用

版权声明:本文为博主汪子熙原创文章,未经博主允许不得转载。 https://jerry.blog.csdn.net/article/details/89842784

源代码如下:

package com.sap.crm.ui.core.pages;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.sap.crm.ui.core.tags.ContainerElement;
import com.sap.crm.ui.core.tags.Element;
import com.sap.crm.ui.core.tags.ElementFactory;
import com.sap.crm.ui.core.tags.ParentElement;
import com.sap.crm.ui.core.tags.SubFactory;
import com.sap.crm.ui.core.tags.UISession;

public class AbstractPage {

	protected final UISession session;
	protected ParentElement container;

	public AbstractPage(final UISession session) {
		super();
		this.session = session;
		init();
	}

	protected void init() {
		final List<Field> fields = new ArrayList<Field>();
		final List<Field> subFields = new ArrayList<Field>();
		Map<Class<? extends SubObject>, Map<String, SubFactory<? extends SubObject>>> subFactories = new HashMap<>();

		Page pageAnnotation = this.getClass().getAnnotation(Page.class);
		Location defaultLocation = null;
		if (pageAnnotation != null) {
			defaultLocation = pageAnnotation.defaultLocation();
		}

		// Retrieve all fields/members that are declared as
		// public/protected/private.
		for (final Field field : this.getClass().getDeclaredFields()) {

			if (!field.isAccessible())
				field.setAccessible(true);

			final Class<?> type = field.getType();
			if (Element.class.isAssignableFrom(type) || type == String.class) {
				if (field.getAnnotation(Container.class) != null) {
					fields.add(0, field);
				} else {
					fields.add(field);
				}

			} else if (AbstractPage.class.isAssignableFrom(type)) {
				// element is inheriting from AbstractPage
				createSubPage(field, type);

			} else if (SubObject.class.isAssignableFrom(type)) {
				// subFactory e.g. for table columns
				subFields.add(field);
			}
		}

		// Now consider all fields that have a PageElement annotation and create
		// the concrete element instances via factory
		for (final Field field : fields) {
			PageElement pageElement = resolveAnnotations(field);

			if (pageElement != null) {
				final Class<?> type = field.getType();
				if (type == String.class) {
					// Just a versioned ID
					setField(field, pageElement.id());
					continue;
				}

				// Determine element type
				@SuppressWarnings("unchecked")
				Class<? extends Element> fieldType = (Class<? extends Element>) type;
				if (pageElement.type() != Element.class) {
					if (!fieldType.isAssignableFrom(pageElement.type())) {
						throw new IllegalArgumentException();
					}

					fieldType = pageElement.type();
				}

				// Get factory dependent from location
				Element element;
				ElementFactory factory = null;

				factory = resolveLocation(factory, pageElement, defaultLocation);

				// Check if proxy needed
				if (ElementFactory.isConcreteType(fieldType)) {
					// Concrete type is known, no proxy needed
					element = factory.element(fieldType, pageElement.id());
				} else {
					// Final Type is not known, need a proxy
					element = factory.proxy(pageElement.id());
				}

				if (field.getAnnotation(Container.class) != null) {
					container = (ContainerElement) element;
				}

				setField(field, element);

				// Remember subFactories
				if (SubFactory.class.isAssignableFrom(fieldType)) {
					registerSubFactory(subFactories, field, fieldType, element);
				}

			}
		}

		// Instantiate subObject fields from factories
		for (Field subField : subFields) {
			PageElement pageElement = resolveAnnotations(subField);

			// Get factory
			Map<String, SubFactory<? extends SubObject>> subFactoriesForType = subFactories
					.get(subField.getType());
			if (subFactoriesForType == null) {
				throw new IllegalArgumentException("Subfactory for type "
						+ subField.getType() + " could not be found on page");
			}
			SubFactory<? extends SubObject> subFactory = subFactoriesForType
					.get(pageElement.subFactoryName());
			if (subFactory == null) {
				throw new IllegalArgumentException("Subfactory for type "
						+ subField.getType() + " with name "
						+ pageElement.subFactoryName()
						+ " could not be found on page");
			}

			// Get parametrization for generic types
			ParameterizedType genericType = (ParameterizedType) subField
					.getGenericType();
			Type[] actualTypeArguments = genericType.getActualTypeArguments();

			// Produce and assign
			Object subObject = subFactory.produce(pageElement.id(),
					actualTypeArguments);
			try {
				subField.set(this, subObject);
			} catch (final IllegalAccessException e) {
				throw new IllegalStateException(e);
			}
		}
	}

	private void setField(final Field field, Object value) {
		try {
			field.set(this, value);
		} catch (final IllegalAccessException e) {
			throw new IllegalStateException(e);
		}
	}

	private void createSubPage(final Field field, final Class<?> type) {
		@SuppressWarnings("unchecked")
		final Class<? extends AbstractPage> pageType = (Class<AbstractPage>) type;
		// Create sub pages
		try {
			final Constructor<? extends AbstractPage> constructor = pageType
					.getConstructor(UISession.class);
			try {
				final AbstractPage page = constructor.newInstance(session);
				field.set(this, page);
			} catch (final IllegalArgumentException e) {
				e.printStackTrace();
			} catch (final InstantiationException e) {
				e.printStackTrace();
			} catch (final IllegalAccessException e) {
				e.printStackTrace();
			} catch (final InvocationTargetException e) {
				e.printStackTrace();
			}
		} catch (final NoSuchMethodException e) {
			// Ignore it, has to be coded manually
		}
	}

	private ElementFactory resolveLocation(ElementFactory factory,
			PageElement pageElement, Location defaultLocation) {
		Location location = pageElement.location();
		if (location == Location.DEFAULT && defaultLocation != null) {
			location = defaultLocation;
		}

		switch (location) {
		case ROOT:
			factory = session.ui();
			break;
		case CONTAINER:
			factory = container.contained();
			break;
		case DEFAULT:
			if (container != null) {
				factory = container.contained();
			} else {
				factory = session.workArea();
			}
			break;
		case TOOLBAR:
			factory = session.getToolbarFactory();
			break;
		case WORK_AREA:
			factory = session.workArea();
			break;
		}
		return factory;
	}

	private void registerSubFactory(
			Map<Class<? extends SubObject>, Map<String, SubFactory<? extends SubObject>>> subFactories,
			final Field field, Class<? extends Element> fieldType,
			Element element) {

		@SuppressWarnings("unchecked")
		SubFactory<? extends SubObject> subFactory = (SubFactory<? extends SubObject>) element;

		// Determine Name
		com.sap.crm.ui.core.pages.SubFactory annotation = field
				.getAnnotation(com.sap.crm.ui.core.pages.SubFactory.class);
		String subFactoryName = (annotation != null) ? annotation.name() : "";

		Class<? extends SubObject> targetType = findSubObjectFactoryTargetType(fieldType);
		Map<String, SubFactory<? extends SubObject>> subFactoriesForType = subFactories
				.get(targetType);
		if (subFactoriesForType == null) {
			subFactoriesForType = new HashMap<>();
			subFactories.put(targetType, subFactoriesForType);
		}

		if (subFactoriesForType.put(subFactoryName, subFactory) != null) {
			throw new IllegalStateException(
					"Ambiguous subObjectFactories on page for type "
							+ targetType + " with name " + subFactoryName);
		}
	}

	@SuppressWarnings("unchecked")
	private Class<? extends SubObject> findSubObjectFactoryTargetType(
			Class<? extends Element> fieldType) {
		Type[] genericInterfaces = fieldType.getGenericInterfaces();
		for (Type intf : genericInterfaces) {
			if (intf instanceof ParameterizedType
					&& ((ParameterizedType) intf).getRawType() == SubFactory.class) {
				Type[] actualTypeArguments = ((ParameterizedType) intf)
						.getActualTypeArguments();
				Type type = actualTypeArguments[0];
				Class<? extends SubObject> targetType;
				if (type instanceof ParameterizedType) {
					targetType = (Class<? extends SubObject>) ((ParameterizedType) type)
							.getRawType();

				} else {
					targetType = (Class<? extends SubObject>) type;
				}
				return targetType;
			}
		}
		throw new IllegalArgumentException();
	}

	private PageElement resolveAnnotations(final Field field) {
		// Fetch annotations
		final Versioned versionedAnnotation = field
				.getAnnotation(Versioned.class);
		PageElement pageElement = field.getAnnotation(PageElement.class);

		// Process versions
		if (versionedAnnotation != null) {
			int highestVersion = 0;
			for (final Version version : versionedAnnotation.versions()) {
				if (version.majorVersion() >= session.getMajorVersion()
						&& version.majorVersion() > highestVersion) {
					pageElement = version.element();
					highestVersion = version.majorVersion();
				}
			}
		}
		return pageElement;
	}
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • One order deletion tool

    版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons)

    Jerry Wang
  • 一些通过SAP ABAP代码审查得出的ABAP编程最佳实践

    版权声明:本文为博主汪子熙原创文章,未经博主允许不得转载。 https://jerry.blog....

    Jerry Wang
  • Fiori Elements detail table data request logic

    Jerry Wang
  • Swift 两个数组的交集 II - LeetCode

    给定两个数组,写一个方法来计算它们的交集。 例如: 给定 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2].

    韦弦zhy
  • 基于HTML5和WebGL的3D网络拓扑结构图

    HT_hightopo
  • 基于HTML5和WebGL的3D网络拓扑结构图

    现在,3D模型已经用于各种不同的领域。在医疗行业使用它们制作器官的精确模型;电影行业将它们用于活动的人物、物体以及现实电影;视频游戏产业将它们作为计算机与视频游...

    HT for Web
  • 聊聊Elasticsearch的TimedRunnable

    elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/common/util/concurren...

    codecraft
  • [个人项目]电商价格监控——项目介绍和架构演变

    文章介绍并整理了一直在维护的一个小项目:京东价格监控,并详细整理了该项目前前后后几次重构的技术选型,作为一篇总结。

    后端技术漫谈
  • [个人项目]电商价格监控——项目介绍和架构演变

    文章介绍并整理了一直在维护的一个小项目:京东价格监控,并详细整理了该项目前前后后几次重构的技术选型,作为一篇总结。

    Rude3Knife的公众号
  • flask cors跨域请求(flask 102)

    当调用服务端的域名与服务端不一致(前后端分离)的时候会出现跨域问题,可使用Flask-Cors解决以上问题 安装Flask-Cors pip3 instal...

    用户5760343

扫码关注云+社区

领取腾讯云代金券