Separate each sentence from the text: Hello again, it's time to talk about the different ways we can test our code. Testing is a very big topic. Let's talk about the different types of testing and see where testing fits into a continuous integration pipeline. Testing can save us money too. The earlier in the development process that we catch errors, the less that they are going to cost to fix. A bug that I wrote yesterday, I can quickly fix. A bug that I wrote a year ago could mean I now need to correct some errors in our data. A lot more people become involved as the issue is reported by a customer service team or the testing team. Let's start by grouping up our testing into two types. We have functional testing and non-functional testing. Functional testing is asking the question is the application doing what we planned it to do? I've been asked to add a feature that formats the response from the Bedrock knowledge base. The functional test here is simple. I've sent a query to Bedrock, and I expect a generated response and references to knowledge base articles and any metadata associated with the article. As a software engineer, functional testing starts with unit testing. Unit tests are code written using a unit testing framework like PyTest for Python. A unit test is written to test code in isolation. With our knowledge base example, the unit test would be testing that the code correctly formats the response we expect from Bedrock. There might be some edge cases here, like the knowledge base had no results in the response, and we want to display a different message. We can use frameworks that mock or simulate the responses from Bedrock. There are some specific cases I want to test for. I want to control the simulated response from Bedrock. Remember, we want unit tests to test code in isolation. Mocking Bedrock allows us to just focus on the function when testing. Any time in the development process, I can run all of the unit tests in a project to see if they are passing. Now I see the tests I've added are passing, and older code written by others is passing. This is a form of regression testing. I want to be sure the changes I've made haven't broken any of the existing functionality. If I make my changes for the knowledge base feature, but I break other parts of the application, I've created a regression bug. I really don't want to do that. So, I make sure all unit tests are passing. Integration testing expands the scope of the testing. We're no longer testing just one module. We're now testing the interactions of one or more modules. Next, we have nonfunctional testing. This is testing the application for areas outside of functionality, like code quality, security, and performance. Software engineers can decide on standards for code quality. If we all work to the same standards, the code is more readable and easier to maintain. There are tools to enforce code quality standards. We also need to be sure of the security of the application. We want to be sure bad actors cannot damage our application or gain access to something that they shouldn't. We can use tools to automatically check for cybersecurity vulnerabilities. A lot of good security comes from keeping library dependencies up to date. We can also work with experts in penetration testing who can simulate a cyber-attack against our system. Next, it's important to test the performance of your application. How is our system going to respond to an increase in load? The new feature I wrote is working perfectly fine on my laptop. How is it going to work with 1,000 users? The extra users are great for the business. A failure under increased load is not. We need to work on some performance testing. Before we go to production, we can work with some simulated loads and gather some metrics to be confident our application is going to perform well under load. Okay. That's just a few of the different types of testing we do to avoid bad things from happening when we go to production. While we're talking about continuous integration, we can also focus on the automated tests that can happen with every continuous integration build. So, which of these types of testing can we add to the continuous integration? Unit testing is an obvious benefit for continuous integration. Unit tests run pretty quickly and give us fast feedback on the state of the code. There are some other big benefits of writing unit tests that might not be immediately obvious. Writing good tests is effectively writing documentation. Other developers on the team get a good understanding of what a module does just by looking at the tests. Unit tests make you write better code. This might be a funny way of thinking, but for unit tests to work, we need to write code in a way that is more abstract and allows for an easy switching of implementation when we are mocking other services. What else would we like to add to continuous integration? Code quality testing is another easy add. With every update I push to my application, continuous integration will use a linting tool to tell me if I'm not following some coding conventions. Which leaves integration tests, penetration testing, and performance testing. Do we add these to the continuous integration build? The decision here really depends on how much time this will add to the build. One of the biggest benefits of continuous integration is fast feedback. I want to know if my changes have impacted the build within a few minutes. Integration, penetration, and performance testing can be automated and added to the build, but if they're taking longer than a few minutes, we could add them to a build that runs nightly so we get feedback within a day without slowing down our continuous builds. All forms of testing have the same goal. We want to prevent any defects from getting into production. The earlier we catch the defects, the cheaper they will be to fix. We can also apply some DevOps thinking to automate a lot of our testing so that we get quick feedback if our changes introduce defects.