/*
* Copyright 2015-2017 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.junit.platform.launcher;
import static java.util.Collections.unmodifiableSet;
import static org.junit.platform.commons.meta.API.Usage.Experimental;
import static org.junit.platform.commons.meta.API.Usage.Internal;
import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import org.junit.platform.commons.meta.API;
import org.junit.platform.commons.util.Preconditions;
import org.junit.platform.commons.util.ToStringBuilder;
import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.TestDescriptor.Type;
import org.junit.platform.engine.TestSource;
import org.junit.platform.engine.TestTag;
/**
* Immutable data transfer object that represents a test or container which is
* usually part of a {@link TestPlan}.
*
* @since 1.0
* @see TestPlan
*/
@API(Experimental)
public final class TestIdentifier implements Serializable {
private static final long serialVersionUID = 1L;
private final String uniqueId;
private final String parentId;
private final String displayName;
private final String legacyReportingName;
private final TestSource source;
private final Set<TestTag> tags;
private final Type type;
/**
* Factory for creating a new {@link TestIdentifier} from a {@link TestDescriptor}.
*/
@API(Internal)
public static TestIdentifier from(TestDescriptor testDescriptor) {
Preconditions.notNull(testDescriptor, "TestDescriptor must not be null");
String uniqueId = testDescriptor.getUniqueId().toString();
String displayName = testDescriptor.getDisplayName();
TestSource source = testDescriptor.getSource().orElse(null);
Set<TestTag> tags = testDescriptor.getTags();
Type type = testDescriptor.getType();
String parentId = testDescriptor.getParent().map(
parentDescriptor -> parentDescriptor.getUniqueId().toString()).orElse(null);
String legacyReportingName = testDescriptor.getLegacyReportingName();
return new TestIdentifier(uniqueId, displayName, source, tags, type, parentId, legacyReportingName);
}
TestIdentifier(String uniqueId, String displayName, TestSource source, Set<TestTag> tags, Type type,
String parentId, String legacyReportingName) {
Preconditions.notNull(type, "TestDescriptor.Type must not be null");
this.uniqueId = uniqueId;
this.parentId = parentId;
this.displayName = displayName;
this.source = source;
this.tags = unmodifiableSet(new LinkedHashSet<>(tags));
this.type = type;
this.legacyReportingName = legacyReportingName;
}
/**
* Get the unique ID of the represented test or container.
*
* <p>Uniqueness must be guaranteed across an entire
* {@linkplain TestPlan test plan}, regardless of how many engines are used
* behind the scenes.
*
* @return the unique ID for this identifier; never {@code null}
*/
public String getUniqueId() {
return this.uniqueId;
}
/**
* Get the unique ID of this identifier's parent, if available.
*
* <p>An identifier without a parent is called a <em>root</em>.
*
* @return a container for the unique ID for this identifier's parent;
* never {@code null} though potentially <em>empty</em>
*/
public Optional<String> getParentId() {
return Optional.ofNullable(this.parentId);
}
/**
* Get the display name of the represented test or container.
*
* <p>A <em>display name</em> is a human-readable name for a test or
* container that is typically used for test reporting in IDEs and build
* tools. Display names may contain spaces, special characters, and emoji,
* and the format may be customized by {@link org.junit.platform.engine.TestEngine
* TestEngines} or potentially by end users as well. Consequently, display
* names should never be parsed; rather, they should be used for display
* purposes only.
*
* @return the display name for this identifier; never {@code null} or blank
* @see #getSource()
* @see org.junit.platform.engine.TestDescriptor#getDisplayName()
*/
public String getDisplayName() {
return this.displayName;
}
/**
* Get the name of this identifier in a format that is suitable for legacy
* reporting infrastructure — for example, for reporting systems built
* on the Ant-based XML reporting format for JUnit 4.
*
* <p>The default implementation simply delegates to {@link #getDisplayName()}.
*
* @return the legacy reporting name; never {@code null} or blank
* @see org.junit.platform.engine.TestDescriptor#getLegacyReportingName()
*/
public String getLegacyReportingName() {
return this.legacyReportingName;
}
/**
* Get the underlying descriptor type.
*
* @return the underlying descriptor type; never {@code null}
*/
public Type getType() {
return type;
}
/**
* Determine if this identifier represents a test.
*
* @return {@code true} if the underlying descriptor type represents a test,
* {@code false} otherwise
* @see Type#isTest()
*/
public boolean isTest() {
return getType().isTest();
}
/**
* Determine if this identifier represents a container.
*
* @return {@code true} if the underlying descriptor type represents a container,
* {@code false} otherwise
* @see Type#isContainer()
*/
public boolean isContainer() {
return getType().isContainer();
}
/**
* Get the {@linkplain TestSource source} of the represented test
* or container, if available.
*
* @see TestSource
*/
public Optional<TestSource> getSource() {
return Optional.ofNullable(this.source);
}
/**
* Get the set of {@linkplain TestTag tags} associated with the represented
* test or container.
*
* @see TestTag
*/
public Set<TestTag> getTags() {
return this.tags;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof TestIdentifier) {
TestIdentifier that = (TestIdentifier) obj;
return Objects.equals(this.uniqueId, that.uniqueId);
}
return false;
}
@Override
public int hashCode() {
return this.uniqueId.hashCode();
}
@Override
public String toString() {
// @formatter:off
return new ToStringBuilder(this)
.append("uniqueId", this.uniqueId)
.append("parentId", this.parentId)
.append("displayName", this.displayName)
.append("legacyReportingName", this.legacyReportingName)
.append("source", this.source)
.append("tags", this.tags)
.append("type", this.type)
.toString();
// @formatter:on
}
}