I have a Allure step method for a parametrized JUnit 5 and Selenium test which receives a test data object containing all the test data for the parametrized test.
This main step method calls other sub step methods. A sub step is only executed if its argument is not null. Thus I can control the test execution by the test data itself. I check for null in the sub step and not in the main step method because the sub step can be called from any test (I do not want to repeat myself).
Example:
#Step
public void trade(TradeData data) {
enterAmount(data.getAmount());
enterCurrency(data.getCurrency());
}
#Step
public void enterAmount(String amount) {
if (amount != null) {
// do something
}
}
#Step
public void enterCurrency(String currency) {
if (currency != null) {
// do something
}
}
In the Allure test report it appears that the sub steps are always executed.
For the above example it always reads like:
trade
enterAmount
enterCurrency
Only if I click on a sub step and see that the argument was null then I can infer that it was not executed. This is not ideal.
Instead I would like that the report displays only the steps which have been executed. Lets assume that only ¨amount¨ is null, then it would look like:
trade
enterCurrency
I can imagine that it would be possible by not using a inflexible #Step annotation and instead calling an Allure method in the if-block to declare the method to be regarded as a step (pseudo code):
public void enterAmount(String amount) {
if (amount != null) {
Allure.context().step();
// do something
}
}
But is this possible somehow with Allure? I prefer an easy way over a very complicated workaround.
You can create helper method that will create step using Allure Lifecycle API:
public static void step(String name, Runnable runnable) {
String uuid = UUID.randomUUID().toString();
StepResult result = new StepResult()
.withName(name);
Allure.getLifecycle().startStep(uuid, result);
try {
runnable.run();
Allure.getLifecycle().updateStep(uuid, s -> s.withStatus(Status.PASSED));
} catch (Throwable e) {
Allure.getLifecycle().updateStep(uuid, s -> s
.withStatus(ResultsUtils.getStatus(e).orElse(Status.BROKEN))
.withStatusDetails(ResultsUtils.getStatusDetails(e).orElse(null)));
throw e;
} finally {
Allure.getLifecycle().stopStep(uuid);
}
}
and then use it like this:
public void enterAmount(String amount) {
if (amount != null) {
step("Enter amount", () -> {
//do something
});
}
}
Related
I have a class of methods, if I want to test one method, but the objects created in this method depend on other methods in the class. I don't want to actually call the other methods, I just want to create mock objects to test. How should I do it?
#Test
public void testLoadException(String id) {
WorkflowExecution mockWorkflowExection = getWorkflowExecution(id);
}
I tried to just do so
WorkflowExecution mockExecution = EasyMock.create(WorkflowExecution.class);
Easy.expect(this.test.getWorkflowExecution(EasyMock.anyString())).andReturn(mockExecution);
But this does not work, the test gives me Nullpointer exception.
So can I skip the calling of getWorkflowExecution(id), Thanks!
You need a partial mock. Your example doesn't make much sense. So here is what you seem to want.
public class WorkflowExecution {
public void theRealMethodIWantToCall() {
theMethodIWantToMock();
}
void theMethodIWantToMock() {
}
}
#Test
public void testLoadException() {
WorkflowExecution execution = partialMockBuilder(WorkflowExecution.class)
.addMockedMethod("theMethodIWantToMock")
.mock();
execution.theMethodIWantToMock();
replay(execution);
execution.theRealMethodIWantToCall();
verify(execution);
}
I am having a very little problem in my Unity project but can't find a proper help or way to do. I am stuck at point where I have an array of prefab GameObjects and I am trying to instantiate index 1 GameObject and when it destroyed instantiate the next index. Here is how I am doing it. I have two scripts: One to instantiate and other one to destroy it.
Scripts 1:
public class GameObjectsArray : MonoBehaviour {
public static GameObjectsArray Instance { get; set; }
public GameObject[] Objects;
public int i=0;
// Use this for initialization
void Start()
{
InstiatingMethod();
//Instantiate(Objects[i]);
}
public void InstiatingMethod()
{
Instantiate(Objects[i]);
}
}
Scripts 2:
public class CheckDestroy : MonoBehaviour {
//public GameObject[] Objects;
//int i;
// Use this for initialization
void Start () {
Debug.Log("executed");
//Objects = GameObject.FindGameObjectsWithTag("Player");
//OnMouseDown();
//Instantiate(Objects[i], transform.position, transform.rotation);
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
BoxCollider boxCollider = hit.collider as BoxCollider;
if (boxCollider != null)
{
GameObjectsArray.Instance.i++;
GameObjectsArray.Instance.InstiatingMethod();
Destroy(boxCollider.gameObject);
}
}
}
}
}
So I created a very quick project to make a good response:
Scene Image
In the scene, we will have an empty game object that will contain our script that I called "GameManager", basically this script will do everything, it's more logic to put your logic in one script.
public GameObject[] GameObjects;
private int _targetIndex = -1;
private RaycastHit _hit;
private void Start()
{
InstantiateNextGameObject();
}
public void InstantiateNextGameObject()
{
//if the index is pointing at the last game object in the array, init the index to -1
if (_targetIndex == GameObjects.Length - 1)
_targetIndex = -1;
Instantiate(GameObjects[++_targetIndex]);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out _hit))
{
BoxCollider boxCollider = _hit.collider as BoxCollider;
if (boxCollider != null)
{
InstantiateNextGameObject();
Destroy(boxCollider.gameObject);
}
}
}
}
we will have an array of gameobjects following with the targetIndex which will start from -1.
The function InstantiateNextGameObject() will simply increment targetIndex and then instantiate a gameobject from the array (++targetIndex the first time will be 0, second time 1 etc). We have to check also if the targetIndex reaches the end of the array, put it back to -1.
Then basically what you did in the update, when you click on a gameobject, instantiate the next one and destroy the current.
At the end, you will get something like that:
https://ayoub-gharbi.org/youba_docs/stackoverflow/stackoverflow01.mp4
Feel free to ask me if you didn't understand anything:)
Happy coding!
//service to mock
public interface ServiceToMock {
public void operateDouble(Double dbValue);
public void operateCar(Car car);
}
//class under test
public class ClassUnderTest {
ServiceToMock service;
public void operateDouble(Double dbValue){
service.operateDouble(dbValue);
}
public void operateObject(Car car){
service.operateCar(car);
}
}
//unit test class
#RunWith(EasyMockRunner.class)
public class TestEasyMockMatcherUnderTest {
#TestSubject
private final ClassUnderTest easyMockMatcherUnderTest = new ClassUnderTest();
#Mock
private ServiceToMock mock;
#Test
public void testOperateCar() {
//record
mock.operateCar(EasyMock.anyObject(Car.class));
EasyMock.expectLastCall();
// replay
EasyMock.replay(mock);
//matcher here...
easyMockMatcherUnderTest.operateObject(EasyMock.anyObject(Car.class));
//easyMockMatcherUnderTest.operateObject(new Car());
// verify
EasyMock.verify(mock);
}
#Test
public void testOperateDouble() {
// record
mock.operateDouble(EasyMock.anyDouble());
EasyMock.expectLastCall();
// replay
EasyMock.replay(mock);
easyMockMatcherUnderTest.operateDouble(EasyMock.anyDouble());
// verify
EasyMock.verify(mock);
}
}
As the above code has shown, I intent to test two methods(operateDouble, operateObject). But things are kinda weird since everything runs fine in the operateDouble block while the compiler complaints an "Illegal state exception: 1 matchers expected, 2 recored." when runnig operateObject. And if commentting the method operateDouble out, the compaint goes away..So what is the difference between Double and my custom object Car, as the Double can also be considered as an object. And why does codes in operateObject runs well when commenting operateDouble method out?
EasyMock.anyDouble and EasyMock.anyObject are not meant to be used in replay mode. They are used to setup your expectations in record mode.
Use this in your first test (testOperateCar):
easyMockMatcherUnderTest.operateObject(new Car());
and something like this in your second (testOperateDouble):
easyMockMatcherUnderTest.operateDouble(1.0);
By the way, you don't need to call EasyMock.expectLastCall. It is only useful if you expect a void method to be called multiple times, for example:
mock.operateCar(EasyMock.anyObject(Car.class));
EasyMock.expectLastCall().times(3);
I have a class that returns an IEnumerable. I then execute these tasks in order. Let's say the class is TaskProvider.
public class TaskProvider {
public IEnumerable<Task> SomeThingsToDo() { return work; }
}
I am executing these with the following:
public void ExecuteTasks(IEnumerable<Task> tasks)
{
var enumerator = tasks.GetEnumerator();
ExecuteNextTask(enumerator);
}
static void ExecuteNextTask(IEnumerator<Task> enumerator)
{
bool moveNextSucceeded = enumerator.MoveNext();
if (!moveNextSucceeded) return;
enumerator
.Current
.ContinueWith(x => ExecuteNextTask(enumerator));
}
Now I have a situation where I might have multiple instances of TaskProvider, each generating a list of tasks. I want each list of tasks to be executed in order, meaning that all the tasks from one provider finish before the next one starts.
Then, most importantly, I need to know when all the tasks are completed.
What's the TPL way of accomplishing this?
(FWIW, I'm using the Async CTP for Silverlight.)
Here's the approach I took, and so far all my tests are passing.
First, I created a unioned enumerable of all the tasks from the various providers:
var tasks = from provider in providers
from task in provider.SomeThingsToDo()
select task;
I believe that part of my original problem was that I did a ToList (more or less) and thus began the execution of the tasks prematurely.
Next, I added a callback to ExecuteTasks and ExecuteNextTask. Admittedly, not as clean as I'd hoped. Here's the revised implementation:
public void ExecuteTasks(IEnumerable<Task> tasks, Action callback)
{
var enumerator = tasks.GetEnumerator();
ExecuteNextTask(enumerator, callback);
}
static void ExecuteNextTask(IEnumerator<Task> enumerator, Action callback)
{
bool moveNextSucceeded = enumerator.MoveNext();
if (!moveNextSucceeded)
{
if (callback != null) callback();
return;
}
enumerator
.Current
.ContinueWith(x => ExecuteNextTask(enumerator, callback));
}
I didn't need a thread-safe structure for storing the list of tasks, because the list is generated only once.
at worst you could have a static concurrentqueue of Ienumerables which you ExecuteNextTask method works it's way through...
something like:
public static class ExecuteController {
private static ConcurrentQueue<IEnumerable<Task>> TaskLists = new ConcurrentQueue<IEnumerable<Task>>();
public void ExecuteTaskList(IEnumerable<Task> tasks) {
TaskLists.Enqueue(tasks);
TryStartExec();
}
public void TryStartExec() {
check if there is a new task list and if so exec it with your code.
possibly need to lock around the dequeue but i think there is an atomic dequeue method on concurrent queue..
}
}
Is there a way to extend Storyboard.Children to have an .AddRange instead of just an .Add?
Using C# extension methods is a convenient way to provide an AddRange method. Be aware it won't be any faster than calling Add multiple times.
Here's one example (you might want to add error checking for nulls and such).
To use, you can either:
sb.Children.AddRange(timelineInst1, timelineInst2);
or pass a list.
sb.Children.AddRange(timelineInsts);
where timelineInst is a list that implements IEnuermable<Timeline>.
public static class StoryboardExtensions
{
public static void AddRange(this TimelineCollection timeline, IEnumerable<Timeline> timelines)
{
foreach (Timeline t in timelines)
{
timeline.Add(t);
}
}
public static void AddRange(this TimelineCollection timeline, params Timeline[] timelines)
{
if (timeline == null || timelines.Length == 0) { return; }
foreach (Timeline t in timelines)
{
timeline.Add(t);
}
}
}