SlideShare uma empresa Scribd logo
1 de 34
1
Confidential
TDD as a Personal Skill
Anatoliy Sakhno is a Test Architect with a solid background in
Healthcare Quality Assurance and experience in software
development and test automation.
Write a
failing
test
Make it
pass
Refactor
2
Confidential
2
Agenda
• TDD Overview
• TDD and Automation Framework
• Test Driven Test Automation (TDTA)
• Q&A
3
Confidential
Integration Test
Fluent and consistent
Test Pyramid
End-to-end Test
Complex, beautiful, and fragile
Unit Test
Solid and valuable
Does the whole system work?
Does our code works against the
code we cannot change?
Do our objects do the right thing,
are they convenient to work with?
*Growing Object-Oriented Software, Guided by Tests 1st Edition by Steve Freeman and Nat
Pryce
4
Confidential
Typical tests suite buildout
5
Confidential
Typical tests suite buildout
Failures analysis
6
Confidential
6
Test Driven Development
7
Confidential
What is a TDD?
Write a
failing
test
Make it
pass
Refactor
Code
Fix
bugs
Write
test
Code
Fix
bugs
Forget
8
Confidential
The Value of Unit Tests
Short Feedback Cycle
Debug Refactor Quality
Gate
9
Confidential
Sluggish debug practices:
 Breakpoints
 Step-by-step execution
 Reuse of e2e tests (as is, or by commenting out the
parts that are out of focus)
 Use of temporary tests or scripts
(TestRegistrationDebug.java, temp11.py, etc.)
First Rule of Debugging: Don’t Use the Debugger
10
Confidential
Effective Debug: Make feedback loop even shorter
Unit Test
Meaningful Custom Exception
[Debug] and [Verbose] logging
Clean Code & Patterns-Driven Objects
11
Confidential
Refactoring
• Rename or move code elements
• Extract method (AQA: Extracting methods to BaseTest class is a bad pattern*)
• Extract class (AQA: Extracting classes as Helpers is a bad pattern**)
• Apply design pattern (AQA: DTO, Builders, Factories is your bare minimum)
* Bloated BaseTest is a Large Class antipattern
** Helper name hides the real purpose of a class. Example: DeviceHelper could implement DeviceBuilder,
DeviceFactory, DeviceEmulator, DeviceConfiguration, DeviceDataGenerator or mix of above
Code refactoring is the process of restructuring existing code without changing its external behavior.
12
Confidential
Benefits of having unit tests while coding
• Code execution runs take less time
• Coding focus is not interrupted (flow state makes you more
effective)
• Less metathesiophobia (fear of changes)
• Better code (due to refactoring-friendly environment)
With unit tests the refactoring usually occurs before the code becomes unsupportable
13
Confidential
Quality Gate
TAF quality gate usually includes:
- Some smoke tests;
- A subset (or full set) of integration tests;
- Validation unit tests;
Note: Usually you do have functional test suite which can be
reused as a quality gate for the TAF codebase. But such suites
takes more time to execute and might include unrelated failures.
A quality gate is a set of conditions that needs to be met before you can merge your commit into a
protected branch (for example, the master)
14
Confidential
14
Test Driven TAF Development
15
Confidential
 TDD: create a dedicated test for any task (class) I am going to
spend more than 30 minutes. After debug is done, some delete the
test if you don’t see it’s value for refactoring/quality gate/validation.
 Refactor as you go: write a validation/unit test for the objects (API
Wrapper, Business Layer Objects, Configuration Objects (Helpers),
Data Access & Data Generation objects, etc.) which are used by
your tests more than 5 times.
I don’t create tests for simple functions and objects. Also there is no
need to create tests for page objects unless you need to handle untrivial
UI behavior.
My TDD Rules
16
Confidential
TDD Test Automation System Buildout
End-to-end Test
Integration Test (Isolated
API tests)
Framework Validation Unit Test
Does the whole system work?
Does our code works against the
code we cannot change?
Do framework objects do the right
thing, are they convenient to work
with?
17
Confidential
17
Test Driven TAF Development:
Examples
18
Confidential
Example: Validate your Objects (Log Parsing and Comparison )
Cloud Service
Streaming
Device
HTTP
stream
gRPC
stream
Client App
19
Confidential
Example: Validate your Objects (Log Parsing and Comparison )
@pytest.fixture(scope="module")
def stream_id():
return "31e45c5c-7073-4941-bd64-e2f43238cad8"
@pytest.fixture(scope="module")
def device_log():
return StreamLog(
file_name=f"./output/{stream_id}.device.grpc.log",
log_type=LogType.device,
)
@pytest.fixture(scope="module")
def client_log():
return StreamLog(
file_name=f"./output/{stream_id}.client.http.log",
log_type=LogType.client_grpc,
)
@pytest.mark.validation
def test_http_client_log_matches_device(device_log, client_log):
assert device_log == client_log , "stream content should be the same"
20
Confidential
Example: Unit Test as Example
public class AccountBuilderExample {
@Test(groups = { “presentation", “example" }, description =
“AccountBuilderExample")
public void buildAccount() {
String ownerName = "Павло Полуботок";
Account account = new Account.AccountBuilder("Saving Account", ownerName,
1111l)
.balance(1000000000000.32)
.interest(4.5)
.type("SAVING")
.build();
System.out.println(account);
Assert.assertEquals(account.getOwner(), ownerName);
}
}
21
Confidential
Example: Unit Test as HealthCheck
22
Confidential
Example: Unit Test as HealthCheck
public class RequestGeneratorValidation {
private User doctor = null;
@BeforeClass(alwaysRun = true)
@Parameters({ "Username", "Password" })
public void BeforeClass(String Username, String Password, ITestContext context) {
doctor = new User(Username, Password);
AppConfig.loadConfig();
}
@Test(groups = { "smoke", "validation", "aws" })
public void validateRequestsGeneratorHealth_Aws() {
AppConfig.setIsAWSMode(true);
RequestGenerator generator = new RequestGenerator(AppConfig.getWebDriver(),
AppConfig.getHospitalUrl());// AWS Device Farm Desktop
assert generator.healthCheck(doctor);
}
@Test(groups = { "smoke", "validation" })
public void validateRequestsGeneratorHealth_Local() {
AppConfig.setIsAWSMode(false);
RequestGenerator generator = new RequestGenerator(AppConfig.getWebDriver(),
AppConfig.getHospitalUrl()); // local selenium driver
assert generator.healthCheck(doctor);
}
}
23
Confidential
Example: Make it work from test (1)
@pytest.mark.validation
def test_advertising_manufacture_data(
device_type=1002,
serial_number=203030142,
expected_manufacture_data="41:45:02:0c:19:f1:7e:3b:ba:03:01:0b",
):
config = EmulatorConfig("config.ini")
device_info = DeviceInfoFactory().create_device_info(
device_type=device_type, firmware_revision=config.firmware_revision
)
manufacture_data = (
struct.pack("HB", config.company_id, device_info.product_id)
+ struct.pack(">L", serial_number)
+ struct.pack(">H", device_type)
+ struct.pack(">L", device_info.firmware_revision)[1:]
)
logging.debug(
f"manufacture_data: {','.join( '0x%02x' %i for i in manufacture_data) }"
)
assert ":".join("%02x" % i for i in manufacture_data) == expected_manufacture_data
24
Confidential
Example: Make it work from test (2)
@pytest.mark.validation
def test_advertising_manufacture_data(
device_type="1002",
serial_number=203030142,
expected_manufacture_data="41:45:02:0c:19:f1:7e:3b:ba:03:01:0b",
):
config = EmulatorConfig("config.ini")
device_info = DeviceInfoFactory().create_device_info(
device_type=device_type, firmware_revision=config.firmware_revision
)
device_info.serial_number = serial_number
emulator = deviceEmulator(
config=config,
device_info=device_info,
)
manufacture_data = emulator.get_advertising_string()
assert ":".join("%02x" % i for i in manufacture_data) == expected_manufacture_data
25
Confidential
Example: Walking Skeleton
A Walking Skeleton is a tiny implementation of the system that performs a small end-to-end function.
interface User {
public User register(Application app);
public void unregister();
public User login();
public void logout();
public Something createSomething(Something something);
public Something modifySomething(Something something);
public void deleteSomething(UUID somethingUuid);
}
public class SomethingTest {
public SomethingTest() {
app = GlobalConfig.getApp();
}
@Test(groups = { "validation", "fake" })
public void mockCreateSomething() {
// arrange
User user = new MockUser("Odike, Prince of Nigeria",
"Odike.II@nigeria.gov.ng");
user.register(app)
.login();
// act
Something thing = user.createSomething(new
Something("Special"));
// assert
Assert.assertEquals(thing.getName(), "Special");
}
}
public class UiUser implements User {}
public class ApiUser implements User {}
public class MockUser implements User {}
26
Confidential
Walking Skeleton Example
public class MedReportTest: BaseTest, IClassFixture<MedReportServiceFixture>
, IClassFixture<ConfigFixture>
{
private IMedReportService _service;
private MedReportPdf _pdf;
public MedReportTest(ITestOutputHelper testOutputHelper,
MedReportServiceFixture serviceFixture, ConfigFixture config) : base(testOutputHelper, config)
{
config.ServiceType = AirwayReportServiceType.Fake; // Unit
//config.ServiceType = AirwayReportServiceType.API; // Integration
//config.ServiceType = AirwayReportServiceType.Web; // e2e
_service = serviceFixture.GetService(config);
_pdf = new AirwayReportPdf(_service.GenerateReport(Config.GoldenXml));
}
[Theory]
[Trait("Category", "Validation")]
[InlineData("Age", "67 Y")]
[InlineData("Sex", "Male")]
public void PdfText_PatientDetailsParam(string name, string expectedValue)
{
String param = _pdf.GetPatientDetails().GetPatientParam(name);
param.Should().Be(expectedValue);
}
}
27
Confidential
27
Test Driven Test Automation
Workshop
28
Confidential
Test Driven Test Automation
Write a
failing test
Make it work Refactor
Apply Test
Design
Technique
Make it
work, not
pass :)
29
Confidential
[Story-007] As a Customer I want to add items to the cart So that I prefill my order
public class ShoppingCartTest {
private WebStoreMarket market = GlobalConfig.getMarket();
@Test(groups = { "presentation",
"story-007" }, description = "verify that two items can be added to cart")
public void add2ItemsToCart() {
// ARRANGE
WebStore store = new WebStore("Юшка & Петрушка").register(market);
Product soup = new Product("Юшка", 5.99, ProductType.Grocery);
store.publishProduct(soup, 500);
User customer = new User("Финтик Каленик Кононович",
UserType.RegularCustomer).register(market);
customer.login();
// ACT
customer.addToCart(customer.findProduct(soup), 2);
// ASSERT
List<CartItem> expectedItems = new List<CartItem>() {
{add(new CartItem(soup), 2);}
};
Assert.assertEquals(customer.getCart().getItems(), expectedItems);
}
}
1. SRP is violated
2. Data is hardcoded
3. Test design
techniques cannot be
applied
Typical Approach:
30
Confidential
[Story-007] As a Customer I want to add items to the cart So that I prefill my order
// Step 1: Write a failing test
public class ShoppingCartTest {
private WebStoreMarket market;
public ShoppingCartTest() {
market = GlobalConfig.getMarket();
}
@Test(groups = { "presentation", "story-007" }, description = "verify that items can be added to cart")
public void addItemsToCart(User customer, List<Product> items) {
// ARRANGE
customer.login();
// ACT
for (Product item : items) {
customer.addToCart(customer.findProduct(item), 1);
}
// ASSERT
Cart expectedCart = new Cart(products);
Assert.assertEquals(customer.getCart(), expectedCart);
}
}
31
Confidential
[Story-007] As a Customer I want to add items to the cart So that I prefill my order
// Step 2: Make it Work
@Test(groups = { "presentation",
"story-007" }, dataProvider = "
shopping-cart-cases", description = "verify that
items can be added to cart")
public void addItemsToCart(User customer,
List<Product> items) {
// ARRANGE
customer.login();
// ACT
for (Product item : items) {
customer.addToCart(customer.findProduc
t(item), 1);
}
// ASSERT
Cart expectedCart = new Cart(items);
Assert.assertEquals(customer.getCart(),
expectedCart);
}
@DataProvider(name = "shopping-cart-cases")
public Object[][] shoppingCartCases() {
WebStore store = new WebStore("Юшка & Петрушка")
.register(market);
Product soup = new Product("Юшка", 5.99,
ProductType.Grocery);
store.publishProduct(soup, 500);
User customer = new User("Финтик Каленик Кононович",
UserType.RegularCustomer).register(market);
ArrayList<Product> soup = new ArrayList<Product>() {
{
add(soup);
}
};
return new Object[][] { { customer, soup }};
}
It works, but SRP is still violated
32
Confidential
[Story-007] As a Customer I want to add items to the cart So that I prefill my order
// Step 3: Refactor
@Test(groups = { "presentation",
"story-007" }, dataProvider = " shopping-cart-cases", description = "verify that items can be added to cart")
public void addItemsToCart(User customer, List<Product> items) {
// ARRANGE
customer.login();
// ACT
for (Product item : items) {
customer.addToCart(customer.findProduct(item), 1);
}
// ASSERT
Cart expectedCart = new Cart(items);
Assert.assertEquals(customer.getCart(), expectedCart);
}
@DataProvider(name = "shopping-cart-cases")
public Object[][] shoppingCartCases() {
ProductFactory productFactory = new ProductFactory(new WebStore(“[Story-007] Юшка & Петрушка"), market);
UserFactory userFactory = new UserFactory(market);
return new Object[][] {{ userFactory.getUser(UserType.RegularCustomer), productFactory.getGroceryItem("Юшка") }};
}
33
Confidential
[Story-007] As a Customer I want to add items to the cart So that I prefill my order
// Step 4: Apply Test Design Technique
@Test(groups = { "presentation",
"story-007" }, dataProvider = " shopping-cart-cases", description = "verify that items can be added to cart")
public void addItemsToCart(User customer, List<Product> items) {
// ARRANGE
customer.login();
// ACT
for (Product item : items) {
customer.addToCart(customer.findProduct(item), 1);
}
// ASSERT
Cart expectedCart = new Cart(items);
Assert.assertEquals(customer.getCart(), expectedCart);
}
@DataProvider(name = "shopping-cart-cases")
public Object[][] shoppingCartCases() {
// loop through user types and basic product selection options
ProductFactory productFactory = new ProductFactory(new WebStore(“[Story-007] Юшка & Петрушка"), market);
UserFactory userFactory = new UserFactory(market);
return new Object[][] {
{ userFactory.getUser(UserType.RegularCustomer), productFactory.getStandardMenu(1) },
{ userFactory.getUser(UserType.PremiumCustomer), productFactory.getAdultMenu(1) },
{ userFactory.getUser(UserType.MinorCustomer), productFactory.getProduct("Юшка", 1) },
{ userFactory.getUser(UserType.SystemAdministrator), productFactory. getStandardMenu(2) },
};
}
34
Confidential
34
Q&A

Mais conteúdo relacionado

Mais procurados

Tracking vulnerable JARs
Tracking vulnerable JARsTracking vulnerable JARs
Tracking vulnerable JARs
David Jorm
 
Code Review | 2010
Code Review | 2010Code Review | 2010
Code Review | 2010
Klocwork
 
Resume_Anurag_Design_Verification_2+_yrs
Resume_Anurag_Design_Verification_2+_yrsResume_Anurag_Design_Verification_2+_yrs
Resume_Anurag_Design_Verification_2+_yrs
ANURAG KAVADANA
 
Sonarqube
SonarqubeSonarqube
Sonarqube
Kalkey
 

Mais procurados (20)

Building world-class security response and secure development processes
Building world-class security response and secure development processesBuilding world-class security response and secure development processes
Building world-class security response and secure development processes
 
Tracking vulnerable JARs
Tracking vulnerable JARsTracking vulnerable JARs
Tracking vulnerable JARs
 
BlueHat v18 || Scaling security scanning
BlueHat v18 || Scaling security scanningBlueHat v18 || Scaling security scanning
BlueHat v18 || Scaling security scanning
 
Iot in-production
Iot in-productionIot in-production
Iot in-production
 
Using Kubernetes to make cellular data plans cheaper for 50M users
Using Kubernetes to make cellular data plans cheaper for 50M usersUsing Kubernetes to make cellular data plans cheaper for 50M users
Using Kubernetes to make cellular data plans cheaper for 50M users
 
Improving Automated Tests with Fluent Assertions
Improving Automated Tests with Fluent Assertions Improving Automated Tests with Fluent Assertions
Improving Automated Tests with Fluent Assertions
 
Open Source KMIP Implementation
Open Source KMIP ImplementationOpen Source KMIP Implementation
Open Source KMIP Implementation
 
BlueHat v18 || Record now, decrypt later - future quantum computers are a pre...
BlueHat v18 || Record now, decrypt later - future quantum computers are a pre...BlueHat v18 || Record now, decrypt later - future quantum computers are a pre...
BlueHat v18 || Record now, decrypt later - future quantum computers are a pre...
 
Testing in a Continuous Delivery Pipeline - Better, Faster, Cheaper
Testing in a Continuous Delivery Pipeline - Better, Faster, CheaperTesting in a Continuous Delivery Pipeline - Better, Faster, Cheaper
Testing in a Continuous Delivery Pipeline - Better, Faster, Cheaper
 
Your Application Deserves Better than Kubernetes Ingress: Istio vs. Kubernetes
Your Application Deserves Better than Kubernetes Ingress: Istio vs. KubernetesYour Application Deserves Better than Kubernetes Ingress: Istio vs. Kubernetes
Your Application Deserves Better than Kubernetes Ingress: Istio vs. Kubernetes
 
Customer Case Study: ScienceLogic - Many Paths to Compliance
Customer Case Study: ScienceLogic - Many Paths to ComplianceCustomer Case Study: ScienceLogic - Many Paths to Compliance
Customer Case Study: ScienceLogic - Many Paths to Compliance
 
Fut Lsi
Fut LsiFut Lsi
Fut Lsi
 
How to Build a Basic Edge Cloud
How to Build a Basic Edge CloudHow to Build a Basic Edge Cloud
How to Build a Basic Edge Cloud
 
NAGESH B KALAL
NAGESH B KALALNAGESH B KALAL
NAGESH B KALAL
 
Software Security: In the World of Cloud & CI-CD
Software Security: In the World of Cloud & CI-CDSoftware Security: In the World of Cloud & CI-CD
Software Security: In the World of Cloud & CI-CD
 
Observability and more architecture next 2020
Observability and more   architecture next 2020Observability and more   architecture next 2020
Observability and more architecture next 2020
 
Code Review | 2010
Code Review | 2010Code Review | 2010
Code Review | 2010
 
Resume_Anurag_Design_Verification_2+_yrs
Resume_Anurag_Design_Verification_2+_yrsResume_Anurag_Design_Verification_2+_yrs
Resume_Anurag_Design_Verification_2+_yrs
 
Sonarqube
SonarqubeSonarqube
Sonarqube
 
Securing Apache Web Servers
Securing Apache Web ServersSecuring Apache Web Servers
Securing Apache Web Servers
 

Semelhante a GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Personal Skill”

Test Driven iOS Development (TDD)
Test Driven iOS Development (TDD)Test Driven iOS Development (TDD)
Test Driven iOS Development (TDD)
Babul Mirdha
 
Test driven development
Test driven developmentTest driven development
Test driven development
lukaszkujawa
 

Semelhante a GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Personal Skill” (20)

Stopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestStopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under Test
 
Test driven development in .Net - 2010 + Eclipse
Test driven development in .Net - 2010 + EclipseTest driven development in .Net - 2010 + Eclipse
Test driven development in .Net - 2010 + Eclipse
 
Tdd,Ioc
Tdd,IocTdd,Ioc
Tdd,Ioc
 
Test Driven iOS Development (TDD)
Test Driven iOS Development (TDD)Test Driven iOS Development (TDD)
Test Driven iOS Development (TDD)
 
Unit tests & TDD
Unit tests & TDDUnit tests & TDD
Unit tests & TDD
 
TDD Workshop UTN 2012
TDD Workshop UTN 2012TDD Workshop UTN 2012
TDD Workshop UTN 2012
 
Parasoft .TEST, Write better C# Code Using Data Flow Analysis
Parasoft .TEST, Write better C# Code Using  Data Flow Analysis Parasoft .TEST, Write better C# Code Using  Data Flow Analysis
Parasoft .TEST, Write better C# Code Using Data Flow Analysis
 
System verilog important
System verilog importantSystem verilog important
System verilog important
 
NET Code Testing
NET Code TestingNET Code Testing
NET Code Testing
 
Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"
 
Unit Testing in Flutter - From Workflow Essentials to Complex Scenarios
Unit Testing in Flutter - From Workflow Essentials to Complex ScenariosUnit Testing in Flutter - From Workflow Essentials to Complex Scenarios
Unit Testing in Flutter - From Workflow Essentials to Complex Scenarios
 
Refactoring to Testable Code
Refactoring to Testable CodeRefactoring to Testable Code
Refactoring to Testable Code
 
Binary Studio Academy: .NET Code Testing
Binary Studio Academy: .NET Code TestingBinary Studio Academy: .NET Code Testing
Binary Studio Academy: .NET Code Testing
 
AAA Automated Testing
AAA Automated TestingAAA Automated Testing
AAA Automated Testing
 
Upstate CSCI 540 Unit testing
Upstate CSCI 540 Unit testingUpstate CSCI 540 Unit testing
Upstate CSCI 540 Unit testing
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
An introduction to unit testing
An introduction to unit testingAn introduction to unit testing
An introduction to unit testing
 
Software Engineering - RS3
Software Engineering - RS3Software Engineering - RS3
Software Engineering - RS3
 
Advanced Coded UI Testing
Advanced Coded UI TestingAdvanced Coded UI Testing
Advanced Coded UI Testing
 

Mais de GlobalLogic Ukraine

GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Ukraine
 

Mais de GlobalLogic Ukraine (20)

GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
 
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
 
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
 
Штучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptxШтучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptx
 
Задачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptxЗадачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptx
 
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptxЩо треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
 
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
 
JavaScript Community Webinar #14 "Why Is Git Rebase?"
JavaScript Community Webinar #14 "Why Is Git Rebase?"JavaScript Community Webinar #14 "Why Is Git Rebase?"
JavaScript Community Webinar #14 "Why Is Git Rebase?"
 
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
 
Страх і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic EducationСтрах і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic Education
 
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
 
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic QA Webinar “What does it take to become a Test Engineer”GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
 
“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?
 
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
 
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
 
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
 
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
 
GlobalLogic Webinar "Introduction to Embedded QA"
GlobalLogic Webinar "Introduction to Embedded QA"GlobalLogic Webinar "Introduction to Embedded QA"
GlobalLogic Webinar "Introduction to Embedded QA"
 
C++ Webinar "Why Should You Learn C++ in 2021-22?"
C++ Webinar "Why Should You Learn C++ in 2021-22?"C++ Webinar "Why Should You Learn C++ in 2021-22?"
C++ Webinar "Why Should You Learn C++ in 2021-22?"
 
GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...
GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...
GlobalLogic Test Automation Live Testing Session “Android Behind UI — Testing...
 

Último

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Último (20)

ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 

GlobalLogic Test Automation Online TechTalk “Test Driven Development as a Personal Skill”

  • 1. 1 Confidential TDD as a Personal Skill Anatoliy Sakhno is a Test Architect with a solid background in Healthcare Quality Assurance and experience in software development and test automation. Write a failing test Make it pass Refactor
  • 2. 2 Confidential 2 Agenda • TDD Overview • TDD and Automation Framework • Test Driven Test Automation (TDTA) • Q&A
  • 3. 3 Confidential Integration Test Fluent and consistent Test Pyramid End-to-end Test Complex, beautiful, and fragile Unit Test Solid and valuable Does the whole system work? Does our code works against the code we cannot change? Do our objects do the right thing, are they convenient to work with? *Growing Object-Oriented Software, Guided by Tests 1st Edition by Steve Freeman and Nat Pryce
  • 5. 5 Confidential Typical tests suite buildout Failures analysis
  • 7. 7 Confidential What is a TDD? Write a failing test Make it pass Refactor Code Fix bugs Write test Code Fix bugs Forget
  • 8. 8 Confidential The Value of Unit Tests Short Feedback Cycle Debug Refactor Quality Gate
  • 9. 9 Confidential Sluggish debug practices:  Breakpoints  Step-by-step execution  Reuse of e2e tests (as is, or by commenting out the parts that are out of focus)  Use of temporary tests or scripts (TestRegistrationDebug.java, temp11.py, etc.) First Rule of Debugging: Don’t Use the Debugger
  • 10. 10 Confidential Effective Debug: Make feedback loop even shorter Unit Test Meaningful Custom Exception [Debug] and [Verbose] logging Clean Code & Patterns-Driven Objects
  • 11. 11 Confidential Refactoring • Rename or move code elements • Extract method (AQA: Extracting methods to BaseTest class is a bad pattern*) • Extract class (AQA: Extracting classes as Helpers is a bad pattern**) • Apply design pattern (AQA: DTO, Builders, Factories is your bare minimum) * Bloated BaseTest is a Large Class antipattern ** Helper name hides the real purpose of a class. Example: DeviceHelper could implement DeviceBuilder, DeviceFactory, DeviceEmulator, DeviceConfiguration, DeviceDataGenerator or mix of above Code refactoring is the process of restructuring existing code without changing its external behavior.
  • 12. 12 Confidential Benefits of having unit tests while coding • Code execution runs take less time • Coding focus is not interrupted (flow state makes you more effective) • Less metathesiophobia (fear of changes) • Better code (due to refactoring-friendly environment) With unit tests the refactoring usually occurs before the code becomes unsupportable
  • 13. 13 Confidential Quality Gate TAF quality gate usually includes: - Some smoke tests; - A subset (or full set) of integration tests; - Validation unit tests; Note: Usually you do have functional test suite which can be reused as a quality gate for the TAF codebase. But such suites takes more time to execute and might include unrelated failures. A quality gate is a set of conditions that needs to be met before you can merge your commit into a protected branch (for example, the master)
  • 15. 15 Confidential  TDD: create a dedicated test for any task (class) I am going to spend more than 30 minutes. After debug is done, some delete the test if you don’t see it’s value for refactoring/quality gate/validation.  Refactor as you go: write a validation/unit test for the objects (API Wrapper, Business Layer Objects, Configuration Objects (Helpers), Data Access & Data Generation objects, etc.) which are used by your tests more than 5 times. I don’t create tests for simple functions and objects. Also there is no need to create tests for page objects unless you need to handle untrivial UI behavior. My TDD Rules
  • 16. 16 Confidential TDD Test Automation System Buildout End-to-end Test Integration Test (Isolated API tests) Framework Validation Unit Test Does the whole system work? Does our code works against the code we cannot change? Do framework objects do the right thing, are they convenient to work with?
  • 17. 17 Confidential 17 Test Driven TAF Development: Examples
  • 18. 18 Confidential Example: Validate your Objects (Log Parsing and Comparison ) Cloud Service Streaming Device HTTP stream gRPC stream Client App
  • 19. 19 Confidential Example: Validate your Objects (Log Parsing and Comparison ) @pytest.fixture(scope="module") def stream_id(): return "31e45c5c-7073-4941-bd64-e2f43238cad8" @pytest.fixture(scope="module") def device_log(): return StreamLog( file_name=f"./output/{stream_id}.device.grpc.log", log_type=LogType.device, ) @pytest.fixture(scope="module") def client_log(): return StreamLog( file_name=f"./output/{stream_id}.client.http.log", log_type=LogType.client_grpc, ) @pytest.mark.validation def test_http_client_log_matches_device(device_log, client_log): assert device_log == client_log , "stream content should be the same"
  • 20. 20 Confidential Example: Unit Test as Example public class AccountBuilderExample { @Test(groups = { “presentation", “example" }, description = “AccountBuilderExample") public void buildAccount() { String ownerName = "Павло Полуботок"; Account account = new Account.AccountBuilder("Saving Account", ownerName, 1111l) .balance(1000000000000.32) .interest(4.5) .type("SAVING") .build(); System.out.println(account); Assert.assertEquals(account.getOwner(), ownerName); } }
  • 22. 22 Confidential Example: Unit Test as HealthCheck public class RequestGeneratorValidation { private User doctor = null; @BeforeClass(alwaysRun = true) @Parameters({ "Username", "Password" }) public void BeforeClass(String Username, String Password, ITestContext context) { doctor = new User(Username, Password); AppConfig.loadConfig(); } @Test(groups = { "smoke", "validation", "aws" }) public void validateRequestsGeneratorHealth_Aws() { AppConfig.setIsAWSMode(true); RequestGenerator generator = new RequestGenerator(AppConfig.getWebDriver(), AppConfig.getHospitalUrl());// AWS Device Farm Desktop assert generator.healthCheck(doctor); } @Test(groups = { "smoke", "validation" }) public void validateRequestsGeneratorHealth_Local() { AppConfig.setIsAWSMode(false); RequestGenerator generator = new RequestGenerator(AppConfig.getWebDriver(), AppConfig.getHospitalUrl()); // local selenium driver assert generator.healthCheck(doctor); } }
  • 23. 23 Confidential Example: Make it work from test (1) @pytest.mark.validation def test_advertising_manufacture_data( device_type=1002, serial_number=203030142, expected_manufacture_data="41:45:02:0c:19:f1:7e:3b:ba:03:01:0b", ): config = EmulatorConfig("config.ini") device_info = DeviceInfoFactory().create_device_info( device_type=device_type, firmware_revision=config.firmware_revision ) manufacture_data = ( struct.pack("HB", config.company_id, device_info.product_id) + struct.pack(">L", serial_number) + struct.pack(">H", device_type) + struct.pack(">L", device_info.firmware_revision)[1:] ) logging.debug( f"manufacture_data: {','.join( '0x%02x' %i for i in manufacture_data) }" ) assert ":".join("%02x" % i for i in manufacture_data) == expected_manufacture_data
  • 24. 24 Confidential Example: Make it work from test (2) @pytest.mark.validation def test_advertising_manufacture_data( device_type="1002", serial_number=203030142, expected_manufacture_data="41:45:02:0c:19:f1:7e:3b:ba:03:01:0b", ): config = EmulatorConfig("config.ini") device_info = DeviceInfoFactory().create_device_info( device_type=device_type, firmware_revision=config.firmware_revision ) device_info.serial_number = serial_number emulator = deviceEmulator( config=config, device_info=device_info, ) manufacture_data = emulator.get_advertising_string() assert ":".join("%02x" % i for i in manufacture_data) == expected_manufacture_data
  • 25. 25 Confidential Example: Walking Skeleton A Walking Skeleton is a tiny implementation of the system that performs a small end-to-end function. interface User { public User register(Application app); public void unregister(); public User login(); public void logout(); public Something createSomething(Something something); public Something modifySomething(Something something); public void deleteSomething(UUID somethingUuid); } public class SomethingTest { public SomethingTest() { app = GlobalConfig.getApp(); } @Test(groups = { "validation", "fake" }) public void mockCreateSomething() { // arrange User user = new MockUser("Odike, Prince of Nigeria", "Odike.II@nigeria.gov.ng"); user.register(app) .login(); // act Something thing = user.createSomething(new Something("Special")); // assert Assert.assertEquals(thing.getName(), "Special"); } } public class UiUser implements User {} public class ApiUser implements User {} public class MockUser implements User {}
  • 26. 26 Confidential Walking Skeleton Example public class MedReportTest: BaseTest, IClassFixture<MedReportServiceFixture> , IClassFixture<ConfigFixture> { private IMedReportService _service; private MedReportPdf _pdf; public MedReportTest(ITestOutputHelper testOutputHelper, MedReportServiceFixture serviceFixture, ConfigFixture config) : base(testOutputHelper, config) { config.ServiceType = AirwayReportServiceType.Fake; // Unit //config.ServiceType = AirwayReportServiceType.API; // Integration //config.ServiceType = AirwayReportServiceType.Web; // e2e _service = serviceFixture.GetService(config); _pdf = new AirwayReportPdf(_service.GenerateReport(Config.GoldenXml)); } [Theory] [Trait("Category", "Validation")] [InlineData("Age", "67 Y")] [InlineData("Sex", "Male")] public void PdfText_PatientDetailsParam(string name, string expectedValue) { String param = _pdf.GetPatientDetails().GetPatientParam(name); param.Should().Be(expectedValue); } }
  • 27. 27 Confidential 27 Test Driven Test Automation Workshop
  • 28. 28 Confidential Test Driven Test Automation Write a failing test Make it work Refactor Apply Test Design Technique Make it work, not pass :)
  • 29. 29 Confidential [Story-007] As a Customer I want to add items to the cart So that I prefill my order public class ShoppingCartTest { private WebStoreMarket market = GlobalConfig.getMarket(); @Test(groups = { "presentation", "story-007" }, description = "verify that two items can be added to cart") public void add2ItemsToCart() { // ARRANGE WebStore store = new WebStore("Юшка & Петрушка").register(market); Product soup = new Product("Юшка", 5.99, ProductType.Grocery); store.publishProduct(soup, 500); User customer = new User("Финтик Каленик Кононович", UserType.RegularCustomer).register(market); customer.login(); // ACT customer.addToCart(customer.findProduct(soup), 2); // ASSERT List<CartItem> expectedItems = new List<CartItem>() { {add(new CartItem(soup), 2);} }; Assert.assertEquals(customer.getCart().getItems(), expectedItems); } } 1. SRP is violated 2. Data is hardcoded 3. Test design techniques cannot be applied Typical Approach:
  • 30. 30 Confidential [Story-007] As a Customer I want to add items to the cart So that I prefill my order // Step 1: Write a failing test public class ShoppingCartTest { private WebStoreMarket market; public ShoppingCartTest() { market = GlobalConfig.getMarket(); } @Test(groups = { "presentation", "story-007" }, description = "verify that items can be added to cart") public void addItemsToCart(User customer, List<Product> items) { // ARRANGE customer.login(); // ACT for (Product item : items) { customer.addToCart(customer.findProduct(item), 1); } // ASSERT Cart expectedCart = new Cart(products); Assert.assertEquals(customer.getCart(), expectedCart); } }
  • 31. 31 Confidential [Story-007] As a Customer I want to add items to the cart So that I prefill my order // Step 2: Make it Work @Test(groups = { "presentation", "story-007" }, dataProvider = " shopping-cart-cases", description = "verify that items can be added to cart") public void addItemsToCart(User customer, List<Product> items) { // ARRANGE customer.login(); // ACT for (Product item : items) { customer.addToCart(customer.findProduc t(item), 1); } // ASSERT Cart expectedCart = new Cart(items); Assert.assertEquals(customer.getCart(), expectedCart); } @DataProvider(name = "shopping-cart-cases") public Object[][] shoppingCartCases() { WebStore store = new WebStore("Юшка & Петрушка") .register(market); Product soup = new Product("Юшка", 5.99, ProductType.Grocery); store.publishProduct(soup, 500); User customer = new User("Финтик Каленик Кононович", UserType.RegularCustomer).register(market); ArrayList<Product> soup = new ArrayList<Product>() { { add(soup); } }; return new Object[][] { { customer, soup }}; } It works, but SRP is still violated
  • 32. 32 Confidential [Story-007] As a Customer I want to add items to the cart So that I prefill my order // Step 3: Refactor @Test(groups = { "presentation", "story-007" }, dataProvider = " shopping-cart-cases", description = "verify that items can be added to cart") public void addItemsToCart(User customer, List<Product> items) { // ARRANGE customer.login(); // ACT for (Product item : items) { customer.addToCart(customer.findProduct(item), 1); } // ASSERT Cart expectedCart = new Cart(items); Assert.assertEquals(customer.getCart(), expectedCart); } @DataProvider(name = "shopping-cart-cases") public Object[][] shoppingCartCases() { ProductFactory productFactory = new ProductFactory(new WebStore(“[Story-007] Юшка & Петрушка"), market); UserFactory userFactory = new UserFactory(market); return new Object[][] {{ userFactory.getUser(UserType.RegularCustomer), productFactory.getGroceryItem("Юшка") }}; }
  • 33. 33 Confidential [Story-007] As a Customer I want to add items to the cart So that I prefill my order // Step 4: Apply Test Design Technique @Test(groups = { "presentation", "story-007" }, dataProvider = " shopping-cart-cases", description = "verify that items can be added to cart") public void addItemsToCart(User customer, List<Product> items) { // ARRANGE customer.login(); // ACT for (Product item : items) { customer.addToCart(customer.findProduct(item), 1); } // ASSERT Cart expectedCart = new Cart(items); Assert.assertEquals(customer.getCart(), expectedCart); } @DataProvider(name = "shopping-cart-cases") public Object[][] shoppingCartCases() { // loop through user types and basic product selection options ProductFactory productFactory = new ProductFactory(new WebStore(“[Story-007] Юшка & Петрушка"), market); UserFactory userFactory = new UserFactory(market); return new Object[][] { { userFactory.getUser(UserType.RegularCustomer), productFactory.getStandardMenu(1) }, { userFactory.getUser(UserType.PremiumCustomer), productFactory.getAdultMenu(1) }, { userFactory.getUser(UserType.MinorCustomer), productFactory.getProduct("Юшка", 1) }, { userFactory.getUser(UserType.SystemAdministrator), productFactory. getStandardMenu(2) }, }; }