Testing Is Bad For Developer Productivity

Continuous Delivery
28 Feb 202408:07

Summary

TLDRThe video discusses how testing can negatively impact developer productivity if not treated as a first-class activity. Key issues include writing tests for complex legacy code, struggling to determine what/how to test, and long test runtimes. Solutions involve testing early, thinking deeply about requirements when writing tests, optimizing for test speed, and recognizing that testing is integral to development. The overall message is to make testing a priority, not an afterthought, to improve productivity.

Takeaways

  • 🛠️ Writing tests for existing code is challenging due to lack of clarity on the code's functionality and the trade-offs made during its development.
  • 📝 Writing tests as close as possible to the time of writing the production code, ideally beforehand, ensures better testability and understanding.
  • 🔥 Tests that take a long time to run disrupt developers' flow and productivity, emphasizing the need for fast, efficient testing practices.
  • 🤖 Thinking critically about what to test and how to test it is a crucial part of a developer's job, enhancing code quality and reliability.
  • 📈 Treating testing as a first-class citizen in the development process is essential for maintaining high standards of quality and performance.
  • 📱 Utilizing techniques like running tests in parallel and predictive test selection can significantly reduce testing time and improve efficiency.
  • 👍 Prioritizing the development of tests that can run quickly and independently, without the need for complex setups or dependencies, enhances agility.
  • 📚 Documenting assumptions and expected behaviors through automated tests serves as valuable, continuously validated documentation for developers.
  • 🚀 Embracing a mindset of continuous integration and delivery requires integrating testing deeply into the development workflow for constant feedback.
  • 💻 Making tests a core part of the development process ensures that changes do not inadvertently break existing functionalities.

Q & A

  • What is the main concern addressed regarding testing in software development?

    -The main concern addressed is that testing is often viewed as detrimental to developer productivity, leading to frustration and the feeling of not completing work efficiently.

  • Why is writing tests for existing code challenging?

    -Writing tests for existing code is challenging because developers may not remember the specifics of the code, including its intended functionality and the trade-offs made during its development, making it hard to know which tests to write.

  • What is the recommended approach to writing tests according to the video?

    -The recommended approach is to write tests as close as possible to the time of writing the production code, ideally beforehand, to ensure the code is easier to test and to avoid jeopardizing existing features.

  • What makes it hard to write tests, even when developers are ready and willing?

    -It's difficult to know what the tests should be, how to test the code effectively, and under which circumstances to test to ensure the code works correctly, requiring significant thought and planning.

  • How does writing tests benefit the development process?

    -Writing tests documents the expected behavior of the code under various conditions, assists in thinking through the code's functionality, and provides a continuously verified documentation through automated tests.

  • What issue do long-running tests pose to developer productivity?

    -Long-running tests interrupt the development flow by causing delays in feedback, leading to context switching and reduced efficiency.

  • What strategies can be employed to make tests run faster?

    -Strategies include pushing tests down the testing pyramid, making unit tests run quickly without external dependencies, running tests in parallel, and using predictive test selection to run a subset of tests.

  • Why is treating testing as a first-class citizen important in software development?

    -Treating testing as a first-class citizen ensures that tests are given priority, leading to fast-performing tests that enhance productivity and ensure that assumptions about code functionality are continuously validated.

  • What is the significance of thinking about what to test in the development process?

    -The thinking process involved in deciding what to test is crucial as it involves thorough consideration of the code's behavior and functionality, which is a fundamental aspect of a developer's job.

  • How does the video suggest supporting the continuous delivery channel?

    -The video suggests supporting the continuous delivery channel through Patreon, implying the value of financial contributions in sustaining the content and efforts of the channel.

Outlines

00:00

🤔 Writing Tests for Existing Code is Challenging

Paragraph 1 discusses the challenges of writing tests for existing code, whether written recently or long ago. Key points are that the code is often difficult to test because it wasn't written with testing in mind, and that it's hard to remember why decisions were made. Recommends writing tests as close as possible to writing the production code so the logic is still fresh.

05:01

🧐 Techniques to Speed Up Slow Test Execution

Paragraph 2 explores issues caused by slow test execution, which interrupts developer flow and productivity. Recommends techniques like moving tests down the testing pyramid, running tests in parallel, and using predictive test selection to reduce feedback loop time. Concludes that fast test execution should be treated as a first-class concern alongside test coverage.

Mindmap

Keywords

💡Developer Productivity

Developer productivity refers to the efficiency and effectiveness with which developers can complete their tasks. In the video, it is highlighted as being negatively impacted by certain testing practices. The script argues that while testing is essential, some approaches to testing can lead to frustration and a feeling of stagnation, thereby reducing the overall productivity of developers. Examples include writing tests for existing code without a clear understanding of its functionality, which can be time-consuming and counterproductive.

💡Writing Tests for Existing Code

This concept involves creating tests for code that has already been written, which can be challenging due to potential lack of documentation or understanding of the code's purpose. The video points out that this is particularly difficult when dealing with legacy code or code that was not designed with testability in mind. It emphasizes the importance of writing tests as close as possible to the time of writing the production code to avoid these issues.

💡Testability

Testability refers to the ease with which software can be tested. The video suggests that code should ideally be written with testing in mind to ensure it is easy to test. This involves considering how to isolate components for testing, how to input test data, and how to check outputs effectively. Improving testability can significantly enhance developer productivity by making the testing process more straightforward and less time-consuming.

💡Legacy Code

Legacy code is referred to in the video as code that has been inherited from someone else or written in the past, which now needs to be tested or modified. It poses a particular challenge because it may not have been written with modern testing practices in mind, making it difficult to test and maintain. The video highlights the importance of approaching legacy code with a strategy to improve its testability and documentation through testing.

💡Integration Tests

Integration tests are a type of testing that checks the interaction between different parts of a software system. The video mentions these tests as potentially time-consuming because they may require a specific environment or dependencies to run. It suggests minimizing reliance on integration tests by using unit tests where possible to improve the speed and efficiency of the testing process.

💡Testing Pyramid

The testing pyramid is a concept mentioned in the video that describes the ideal distribution of different types of tests within a project. It recommends having a large base of fast, isolated unit tests, fewer integration tests, and even fewer high-level end-to-end tests. This structure aims to maximize test coverage and efficiency while minimizing the time required to run tests.

💡Continuous Integration

Continuous Integration (CI) is a development practice where developers frequently integrate code into a shared repository, where it is automatically tested. The video highlights the role of CI in running tests regularly to ensure that the codebase remains in a good state. CI servers can validate assumptions and notify developers if a change has introduced errors, thereby supporting developer productivity by reducing the time spent on identifying and fixing regressions.

💡Test-Driven Development

Although not explicitly mentioned, the principle of Test-Driven Development (TDD) underlies the video's advocacy for writing tests before writing production code. TDD involves writing a failing test before writing the code to make the test pass, ensuring that code is designed to be testable from the start. This practice can lead to better designed, more reliable software and is implied in the recommendation to write tests as close as possible to the production code.

💡Automated Testing

Automated testing involves using software tools to run tests automatically, rather than manually checking all aspects of an application. The video underscores its importance by suggesting that documenting assumptions and expected behaviors in automated tests can serve as a form of live documentation that is verified by CI. This approach improves reliability and developer productivity by ensuring that tests are run consistently and that their results are immediately known.

💡Performance of Tests

The performance of tests, in terms of their execution speed, is highlighted in the video as critical to maintaining developer flow and productivity. Slow-running tests can interrupt the development process, leading to context switching and reduced efficiency. The video advocates for optimizing test performance through practices such as reducing dependencies, simplifying tests, and running tests in parallel, to ensure that they provide rapid feedback without breaking the developer's workflow.

Highlights

Introduction to the impact of testing on developer productivity.

Exploring the challenge of writing tests for existing code.

The difficulties in testing code not designed with testing in mind.

Advocacy for writing tests first to facilitate easier testing.

The importance of testing in close proximity to writing production code.

The challenge of knowing what tests to write and how to write them.

The critical role of thinking in the test writing process.

How documenting decisions through tests improves code understanding.

The issue of long-running tests disrupting development flow.

Strategies for making tests run faster.

The benefits of running tests on a local environment.

Techniques for efficient test execution, such as parallel testing.

The importance of treating testing as a first-class citizen in development.

Emphasizing the need for prompt testing close to development time.

Concluding remarks on the value of testing and thinking in development.

Transcripts

play00:00

I don't have time for testing we've all

play00:02

thought it we've probably all said it

play00:05

and we certainly know of organizations

play00:07

that think it in this video I want to

play00:10

look at what makes testing bad for

play00:12

productivity and what we can do about

play00:17

[Music]

play00:21

it hello I'm Trish G welcome to the

play00:25

continuous delivery Channel if this is

play00:27

your first time here please hit the

play00:29

Subscribe button button and if you like

play00:31

the video please press like now before

play00:34

Dave kicks me off the channel before

play00:35

I've even had a chance to get started I

play00:38

want to cave out what I said in the

play00:40

introduction about tests perhaps leading

play00:42

to poor developer productivity there are

play00:45

some practices and some patterns which

play00:48

get in the way of us being productive as

play00:50

developers linked to testing these kinds

play00:53

of things can lead to frustration and

play00:56

making us feel like we're not getting

play00:58

the job done properly the first pattern

play01:00

I want to explore is writing tests for

play01:02

existing code now this existing code

play01:05

might be something that we wrote a week

play01:06

ago or it might be something that

play01:09

someone else wrote 3 years ago certainly

play01:11

the latter case is more challenging but

play01:13

even the former case where we wrote it a

play01:15

week ago there's a good chance we've

play01:17

forgotten what we did and why we did it

play01:20

writing tests for existing code is

play01:22

challenging we don't always know or

play01:24

remember what the code is supposed to do

play01:27

we don't always know why it works in a

play01:29

particular way we don't necessarily know

play01:31

which decisions were made and which

play01:33

trade-offs were made and so we don't

play01:35

always know which tests to write for the

play01:37

code what's usually more challenging

play01:40

about writing test for existing code

play01:43

particularly code that's not already

play01:44

tested is that this code is usually very

play01:47

difficult to test it's often difficult

play01:50

to poke it with the kinds of values that

play01:51

we want to poke it with and request

play01:54

their answers from it in order to

play01:55

ascertain what happened and did it work

play01:58

correctly code which has not been

play02:00

written with testing in mind is

play02:02

difficult to test Dave and I would

play02:03

probably argue that the thing you need

play02:05

to do is write your tests first

play02:07

therefore any code that you write

play02:08

afterwards will by definition be easier

play02:11

to test this isn't always a luxury that

play02:13

we have when we're working on a legacy

play02:15

code base so writing tests for existing

play02:17

code is a challenging thing the key is

play02:19

to write tests as close as possible to

play02:21

the time that we write the production

play02:23

code ideally perhaps beforehand but if

play02:26

not beforehand then certainly close

play02:28

enough after writing the production code

play02:30

that we can remember what it does and

play02:32

that if we need to make some changes to

play02:33

the production code to make it easier to

play02:35

test we can do that without jeopardizing

play02:37

some feature that's been used by users

play02:39

for 3 years or so the next pattern that

play02:41

I want to look at is it is hard to write

play02:45

tests even if we're ready willing and

play02:48

able and we're about to sit down and

play02:49

write the test for our code it's

play02:51

difficult to know what the test should

play02:53

be how to test the code and what should

play02:57

the code do under certain circumstances

play02:59

and which circumstances should we be

play03:01

looking for in order to test that the

play03:03

code works correctly under certain

play03:05

circumstances it's hard it requires a

play03:08

lot of thinking however thinking is our

play03:11

job this is what we do thinking about

play03:14

what the code does when the user does

play03:16

something weird or what the code does

play03:18

when the connection goes down that's

play03:20

something we're going to have to do

play03:21

whether we're writing a test for it or

play03:24

whether we're writing the code itself

play03:26

this is valuable thinking time that is

play03:28

part of our job and if we do this

play03:30

thinking during the time of writing the

play03:31

test then presumably it will take less

play03:34

time to think about it when we're

play03:35

writing the production code on top of

play03:38

that we get the added bonus of we start

play03:40

writing down the questions that we have

play03:42

what should it do under these

play03:44

circumstances how should it behave when

play03:46

something odd happens so we've written

play03:48

those down in the form of an automated

play03:51

test and documented the decisions we've

play03:53

taken when the user puts a malformed

play03:56

input in then the code should give this

play03:58

kind of error message message when the

play04:00

connection is down then the code should

play04:03

do this so this is now documented it's

play04:06

readable by other developers and

play04:09

moreover this is documentation which is

play04:11

run by a continuous integration server

play04:13

regularly so the CI server is telling us

play04:16

your assumptions are still correct and

play04:18

the code still works the way you thought

play04:19

it did the next thing that gets in the

play04:21

way of us being productive as developers

play04:23

when it comes to testing is tests that

play04:25

take a long time to run this might be

play04:28

integration tests test that require an

play04:30

emulator tests that need to run in a

play04:32

particular environment with a particular

play04:34

setup or even local tests which just

play04:36

happen to have a lot of dependencies and

play04:37

have a lot going on a test that takes a

play04:39

long time to run is not giving us the

play04:41

feedback that we want from our automated

play04:43

tests anything that takes long than

play04:46

probably a minute is going to cause us

play04:48

to get up go somewhere else do something

play04:49

else or check our email generally

play04:52

context switch so that when the result

play04:53

of the test comes in we can't remember

play04:56

what we were doing and what we're

play04:57

supposed to do about this test result

play04:58

whether it's a pass or will fail long

play05:00

running tests kill our flow what we

play05:03

really want to do is run the test check

play05:05

our assertion make sure it works yes it

play05:07

does great onto the next thing or it

play05:09

fails okay I better do something about

play05:11

that we want it to be part of our

play05:13

development flow all the time we don't

play05:15

want to break our flow to wait for the

play05:17

result of a test what can we do about

play05:19

this we should be making our tests as

play05:22

fast as possible of course that means

play05:24

pushing it down the testing pyramid

play05:26

where possible turning integration tests

play05:28

into perhaps a number number of unit

play05:30

tests tests that don't require uh

play05:32

databases network connections big

play05:35

modules that have a lot of startup time

play05:37

things that can run quickly a unit test

play05:39

is not necessarily one test class for a

play05:42

production code uh class but it is

play05:45

something which should be able to run

play05:46

very quickly these tests should also

play05:48

ideally run on our laptop so again the

play05:51

the focus should be trying to make it

play05:53

run as quickly as possible maybe you're

play05:55

going to use something like containers

play05:57

to make your build more reproducible

play05:59

ideally we don't even really want

play06:01

something like that if your test is

play06:02

validation for example you should just

play06:04

be testing input and output and not

play06:06

spinning up lots of different services

play06:08

so where possible our tests should be

play06:10

running as quickly as possible as far

play06:12

down the testing pyramid as possible we

play06:14

can also use techniques like running

play06:16

tests in parallel where possible our

play06:17

build tools usually support this where

play06:19

we can run our tests in parallel um

play06:21

there are all sorts of other techniques

play06:23

things like using predictive test

play06:25

selection to only run a subset of tests

play06:27

that kind of thing there are things that

play06:29

we can do to make our tests run as

play06:31

quickly as possible and we should be

play06:32

investigating those Solutions so that

play06:34

we're not having to wait minutes hours

play06:37

maybe even until the next day to find

play06:39

the results of our automated test that

play06:40

we spent so much time thinking about and

play06:42

implementing overall the answer to the

play06:45

problem of testing slowing us down as

play06:47

developers is to treat testing as a

play06:49

first class citizen it is part of our

play06:52

job thinking about what the code should

play06:55

do is of course what we do but since

play06:57

we're going to be thinking about what

play06:58

the code should do why not write that

play07:00

down somewhere in say an automated test

play07:03

where we can actually check that those

play07:05

assertions and those assumptions are

play07:06

correct all the time and when someone

play07:09

makes some changes they haven't broken

play07:10

some behavior that we expected we should

play07:12

also be treating it like a first class

play07:14

citizen in terms of performance this is

play07:16

not something that should just kind of

play07:17

like run you know maybe when we want to

play07:20

and it takes as long as it takes that's

play07:22

okay cuz it's over there no fast-

play07:24

performing tests are what make us

play07:26

productive so treat tests as a first

play07:28

class citizen

play07:30

write tests as soon as possible to the

play07:32

time at which you write your production

play07:34

code treat them as first class citizens

play07:36

in terms of the performance of those

play07:39

tests and never ever think that the time

play07:42

that you spent thinking about what to

play07:44

test is wasted because the thinking is

play07:47

the thing that takes the time and the

play07:49

thinking is the thing that we get paid

play07:50

for anyway I hope you enjoyed this video

play07:53

if you did please consider supporting

play07:55

the continuous delivery channel on

play07:57

patreon thanks

play08:01

[Music]

Rate This

5.0 / 5 (0 votes)

Benötigen Sie eine Zusammenfassung auf Englisch?