前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java反射机制在UI自动化测试中的一个应用

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

作者头像
Jerry Wang
发布2019-05-29 21:24:51
6590
发布2019-05-29 21:24:51
举报

版权声明:本文为博主汪子熙原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1438605

源代码如下:

代码语言:javascript
复制
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;
	}
}

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年05月05日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档