Как создать тест автоматизации для рабочего процесса - PullRequest
0 голосов
/ 26 мая 2020

Я работаю над проектом рабочего процесса, который имеет 19 сценариев ios для тестирования всей системы и 34 шага.

Итак, мой вопрос: как я могу создать для него тест автоматизации?

Мой текущий подход: создать интегрированный тест для каждого сценария, а затем создать основной системный тест для запуска всех интегрированных тестов.

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace Project1
{
     // Unit tests
    public class UnitTest_step1
    {
        public void RunTest() { }
    }

    public class UnitTest_step2
    {
        public void RunTest() { }
    }

    public class UnitTest_step3
    {
        public void RunTest() { }
    }

    public class UnitTest_step4
    {
        public void RunTest() { }
    }
     // End of unit tests

    public class IntegrationTests
    {

        public void IntegrationTest1()
        {
            UnitTest_step1.RunTest();
            UnitTest_step2.RunTest();
            UnitTest_step4.RunTest();
        }

        public void IntegrationTest2()
        {
            UnitTest_step1.RunTest();
            UnitTest_step2.RunTest();
            UnitTest_step3.RunTest();
            UnitTest_step4.RunTest();
        }

        public void IntegrationTest3()
        {
            UnitTest_step1.RunTest();
            UnitTest_step4.RunTest();
        }

    }



    [TestClass]
    public class SystemTests
    {
        [TestMethod]
        public void Scenario1()
        {
            IntegrationTests.IntegrationTest1()
        }

        [TestMethod]
        public void Scenario2()
        {
            IntegrationTests.IntegrationTest2();
        }

        [TestMethod]
        public void Scenario3()
        {
            IntegrationTests.IntegrationTest3();
        }

        [TestMethod]
        public void ScenarioN()
        {
            IntegrationTests.IntegrationTestN();
        }
    }
}

С уважением.

1 Ответ

1 голос
/ 28 мая 2020

Ну, на мой взгляд, информация, представленная в вашем вопросе, очень абстрактна, а вопрос слишком широк. Ответ зависит от того, как реализован ваш механизм рабочего процесса и каковы ваши системные требования. Требования и детали реализации - вот что определяет ваш подход к тестированию.

Я бы начал с пояснения, какие шаги вы выполняете, передается ли какой-либо контекст данных, какие побочные эффекты вызывают эти шаги (записывает данные в базу данных, отправляет события, вызывает другие системные API и т. д. c.), зависят ли шаги друг от друга и т. д.

Другой вопрос: как вам нужно утверждать результаты после каждого шага или после сценария? Система должна быть тестируемой, и, как правило, каждый шаг должен сопровождаться модульными тестами. Итак, предлагаемый гипотетический подход состоит в том, чтобы покрыть каждый шаг изолированными модульными тестами, а сценарий ios - интеграционными тестами.

Я придумал простой пример, чтобы проиллюстрировать один из общих подходов. Для простоты я предполагаю, что у шагов мало или вообще нет контекста данных и их можно переупорядочить.

namespace Workflow.Test
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System;
    using System.Collections.Generic;

    [TestClass]
    public class SystemTests
    {
        [TestMethod]
        public void Scenario1()
        {
            new Workflow().Run(new Scenario1());
        }

        [TestMethod]
        public void Scenario2()
        {
            new Workflow().Run(new Scenario2());
        }

        // The advantage of explicit steps declaration is test readability.
        // Declarative approach also enables the further possibility of test generation!
        [TestMethod]
        public void MoreExplicitAndDeclarative()
        {
            new Workflow().Run(new List<Type>
            {
                typeof(Step1),
                typeof(Step2),
                typeof(Step3),
            });
        }

        // Step instantiation may be needed if you want to parameterize some steps.
        [TestMethod]
        [DataRow("Custom step")]
        [DataRow("Another step")]
        public void MoreExplicitParameterizedScenario(string customName)
        {
            new Workflow().Run(new List<IRunnable>{
                new Step1(),
                new Step3(customName)
            });
        }
    }

    [TestClass]
    public class StepsUnitTests
    {
        [TestMethod]
        public void Step1DoesWhatWeWant()
        {
            // Mock dependencies

            new Step1().Run();

            // Assert results
        }
    }

    #region Workflow Engine Example

    public interface IRunnable
    {
        void Run();
    }

    public class Workflow
    {
        public void Run(Scenario scenario)
        {
            Run(CreateSteps(scenario.GetStepTypes()));
        }

        public void Run(IEnumerable<Type> stepTypes)
        {
            Run(CreateSteps(stepTypes));
        }

        public void Run(List<IRunnable> steps)
        {
            steps.ForEach(step => step.Run());
        }

        private List<IRunnable> CreateSteps(IEnumerable<Type> stepTypes)
        {
            var steps = new List<IRunnable>();
            foreach (var stepType in stepTypes)
            {
                steps.Add(CreateStep(stepType));
            }

            return steps;
        }

        private IRunnable CreateStep(Type stepType)
            => (IRunnable) Activator.CreateInstance(stepType);
    }

    #endregion


    // Step structure can differ according to system requirements.
    // We may add data context and link steps into pipeline if needed.
    #region Steps

    public abstract class Step : IRunnable
    {
        private readonly string _stepName;

        protected Step(string name)
        {
            _stepName = name;
        }

        public void Run()
        {
            Console.WriteLine($"{_stepName} in action.");
            Invoke();
        }

        public abstract void Invoke();
    }

    public class Step1 : Step
    {
        public Step1() : base(nameof(Step1))
        {
        }

        public override void Invoke()
        {
            // do work
            Console.WriteLine($"Step1 invoked.");
        }
    }

    public class Step2 : Step
    {
        public Step2() : base(nameof(Step2))
        {
        }

        public override void Invoke()
        {
            // do work
            Console.WriteLine($"Step2 invoked.");
        }
    }

    public class Step3 : Step
    {
        public Step3(string customName) : base(customName)
        {

        }

        public Step3() : this(nameof(Step3))
        {
        }

        public override void Invoke()
        {
            // do work
            Console.WriteLine($"Step3 invoked.");
        }
    }

    public class Step4 : Step
    {
        public Step4() : base(nameof(Step4))
        {
        }

        public override void Invoke()
        {
            // do work
            Console.WriteLine($"Step4 invoked.");
        }
    }

    #endregion

    // Scenarios should be as declarative as possible.
    // Let's say the scenario is just specification of what steps (step Type)
    // and in what order should be executed (List as a non-unique ordered collection).
    #region Scenarios

    public abstract class Scenario
    {
        public abstract List<Type> GetStepTypes();
    }

    public class Scenario1 : Scenario
    {
        public override List<Type> GetStepTypes()
            => new List<Type>
            {
                typeof(Step1),
                typeof(Step2),
                typeof(Step3)
            };
    }

    public class Scenario2 : Scenario
    {
        public override List<Type> GetStepTypes()
            => new List<Type>
            {
                typeof(Step1),
                typeof(Step2),
                typeof(Step4)
            };
    }

    #endregion
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...