SlideShare une entreprise Scribd logo
1  sur  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

Contenu connexe

Tendances

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 processesDavid Jorm
 
Tracking vulnerable JARs
Tracking vulnerable JARsTracking vulnerable JARs
Tracking vulnerable JARsDavid Jorm
 
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 usersMirantis
 
Improving Automated Tests with Fluent Assertions
Improving Automated Tests with Fluent Assertions Improving Automated Tests with Fluent Assertions
Improving Automated Tests with Fluent Assertions TestingCR
 
Open Source KMIP Implementation
Open Source KMIP ImplementationOpen Source KMIP Implementation
Open Source KMIP Implementationsedukull
 
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...BlueHat Security Conference
 
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, CheaperGene Gotimer
 
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. KubernetesMirantis
 
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 ComplianceBlack Duck by Synopsys
 
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 CloudMirantis
 
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-CDOWASP Delhi
 
Observability and more architecture next 2020
Observability and more   architecture next 2020Observability and more   architecture next 2020
Observability and more architecture next 2020Alon Fliess
 
Code Review | 2010
Code Review | 2010Code Review | 2010
Code Review | 2010Klocwork
 
Resume_Anurag_Design_Verification_2+_yrs
Resume_Anurag_Design_Verification_2+_yrsResume_Anurag_Design_Verification_2+_yrs
Resume_Anurag_Design_Verification_2+_yrsANURAG KAVADANA
 
Sonarqube
SonarqubeSonarqube
SonarqubeKalkey
 

Tendances (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
 

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

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 TestSeb Rose
 
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 + EclipseUTC Fire & Security
 
Test Driven iOS Development (TDD)
Test Driven iOS Development (TDD)Test Driven iOS Development (TDD)
Test Driven iOS Development (TDD)Babul Mirdha
 
Unit tests & TDD
Unit tests & TDDUnit tests & TDD
Unit tests & TDDDror Helper
 
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 Engineering Software Lab
 
System verilog important
System verilog importantSystem verilog important
System verilog importantelumalai7
 
Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"Fwdays
 
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 ScenariosFlutter Agency
 
Refactoring to Testable Code
Refactoring to Testable CodeRefactoring to Testable Code
Refactoring to Testable CodeRichard Taylor
 
Binary Studio Academy: .NET Code Testing
Binary Studio Academy: .NET Code TestingBinary Studio Academy: .NET Code Testing
Binary Studio Academy: .NET Code TestingBinary Studio
 
Upstate CSCI 540 Unit testing
Upstate CSCI 540 Unit testingUpstate CSCI 540 Unit testing
Upstate CSCI 540 Unit testingDanWooster1
 
Test driven development
Test driven developmentTest driven development
Test driven developmentlukaszkujawa
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testingpleeps
 
An introduction to unit testing
An introduction to unit testingAn introduction to unit testing
An introduction to unit testingAdam Stephensen
 
Software Engineering - RS3
Software Engineering - RS3Software Engineering - RS3
Software Engineering - RS3AtakanAral
 
Advanced Coded UI Testing
Advanced Coded UI TestingAdvanced Coded UI Testing
Advanced Coded UI TestingShai Raiten
 

Similaire à 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
 

Plus de GlobalLogic Ukraine

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”GlobalLogic Ukraine
 
Штучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptxШтучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptxGlobalLogic Ukraine
 
Задачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptxЗадачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptxGlobalLogic Ukraine
 
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptxЩо треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptxGlobalLogic Ukraine
 
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...GlobalLogic Ukraine
 
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 Ukraine
 
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...GlobalLogic Ukraine
 
Страх і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic EducationСтрах і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic EducationGlobalLogic Ukraine
 
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 Ukraine
 
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”GlobalLogic Ukraine
 
“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 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
 
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 Ukraine
 
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”GlobalLogic Ukraine
 
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 Ukraine
 
GlobalLogic Webinar "Introduction to Embedded QA"
GlobalLogic Webinar "Introduction to Embedded QA"GlobalLogic Webinar "Introduction to Embedded QA"
GlobalLogic Webinar "Introduction to Embedded QA"GlobalLogic Ukraine
 
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 Ukraine
 
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...GlobalLogic Ukraine
 
GlobalLogic Azure TechTalk ONLINE “Marketing Data Lake in Azure”
GlobalLogic Azure TechTalk ONLINE “Marketing Data Lake in Azure”GlobalLogic Azure TechTalk ONLINE “Marketing Data Lake in Azure”
GlobalLogic Azure TechTalk ONLINE “Marketing Data Lake in Azure”GlobalLogic Ukraine
 
GlobalLogic Test Automation Online TechTalk “Playwright — A New Hope”
GlobalLogic Test Automation Online TechTalk “Playwright — A New Hope”GlobalLogic Test Automation Online TechTalk “Playwright — A New Hope”
GlobalLogic Test Automation Online TechTalk “Playwright — A New Hope”GlobalLogic Ukraine
 

Plus de GlobalLogic Ukraine (20)

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...
 
GlobalLogic Azure TechTalk ONLINE “Marketing Data Lake in Azure”
GlobalLogic Azure TechTalk ONLINE “Marketing Data Lake in Azure”GlobalLogic Azure TechTalk ONLINE “Marketing Data Lake in Azure”
GlobalLogic Azure TechTalk ONLINE “Marketing Data Lake in Azure”
 
GlobalLogic Test Automation Online TechTalk “Playwright — A New Hope”
GlobalLogic Test Automation Online TechTalk “Playwright — A New Hope”GlobalLogic Test Automation Online TechTalk “Playwright — A New Hope”
GlobalLogic Test Automation Online TechTalk “Playwright — A New Hope”
 

Dernier

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
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 AutomationSafe Software
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
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 Scriptwesley chun
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
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...Enterprise Knowledge
 
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...Martijn de Jong
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 

Dernier (20)

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
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
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
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
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
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...
 
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...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 

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) }, }; }