{"wwdc2024-10195":{"language":"eng","transcript":[[7,"Hi I’m Jonathan and I’m part of the Swift Testing team.\n\n"],[11,"My colleague Dorothy and I, "],[12,"are here to walk you through some of the powerful features in Swift Testing "],[16,"that will elevate your test development to the next level. "],[19,"Swift Testing is a modern, open-source testing library for Swift "],[23,"powerful and expressive capabilities. "],[26,"It's included with Xcode 16. "],[29,"If you haven’t already, "],[30,"watch “Meet Swift Testing” to learn about the building blocks of Swift Testing.\n\n"],[35,"Testing is a crucial step in the development process. "],[38,"It helps surface issues before your code reaches your users "],[42,"and gives you confidence that you’re shipping a quality product. "],[45,"However, you may run into challenges as you maintain your project's "],[48,"ever-growing collection of tests.\n\n"],[51,"Tests document and enforce the behavior of your code. "],[55,"The more complex your code gets, "],[57,"the more critical it is that your tests are easy to read and understand. "],[61,"It takes a lot of thought and effort "],[63,"to cover all possible edge cases in your code.\n\n"],[66,"Organizing and relating a large collection of tests can be a complex task, "],[71,"and hidden dependencies between your tests "],[73,"may make them fragile and prone to unexpected failures. "],[77,"To get us started, here’s Dorothy. "],[79,"The readability of your tests is important. "],[82,"Readable tests are easier to work with, "],[84,"and make test failures more understandable "],[86,"especially as your code gets more and more complex. "],[90,"Swift Testing includes several features "],[92,"that can help you write clear, expressive tests.\n\n"],[96,"Expectations are how you validate "],[97,"that your code is behaving as expected in Swift Testing. "],[101,"They leverage Swift language features and syntax "],[103,"to provide a highly expressive and concise interface.\n\n"],[107,"Here are some examples of expectations "],[109,"with simple expressions that evaluate to true or false. "],[113,"However, the expect macro is much more powerful "],[116,"and can handle even more complicated validations.\n\n"],[120,"Error handling is often less tested "],[122,"but is an important part of the user’s experience. "],[125,"You want to make sure your code fails gracefully in the face of invalid input "],[129,"and unexpected conditions. "],[131,"The expect throws macro make this workflow much easier "],[134,"by building on expectations.\n\n"],[137,"When you’re testing your code's happy path "],[139,"and are expecting a throwing function to return successfully, "],[142,"just call it inside your test.\n\n"],[144,"If the function does end up throwing an error, the test will fail.\n\n"],[148,"If the function runs successfully and returns a value, "],[151,"you can use an expectation to verify that it’s what you're expecting it to be.\n\n"],[156,"On the other hand, to verify failure cases behave as intended, "],[161,"you need to catch, and examine the error, thrown by the function.\n\n"],[165,"You could add your own do catch statement around the code and examine the error, "],[170,"but it's pretty wordy, and if an error is not thrown, "],[173,"this code won't let you know that things went terribly right.\n\n"],[177,"Swift Testing is here to help with the expect throws macro. "],[181,"Instead of manually writing your own do catch statement, "],[184,"the expect throws macro does the hard work for you. "],[187,"If the brew function throws an error, then this test passes. "],[191,"If no error was thrown, the test fails.\n\n"],[196,"If you want to check that a particular type of error is thrown, "],[199,"you can pass that type instead of any Error. "],[202,"Now this test will fail if no error is thrown, "],[204,"or, if any error is thrown that isn't an instance of BrewingError.\n\n"],[209,"To take it one step further, "],[211,"you can be even more thorough and validate that a specific error is thrown. "],[216,"For the most complex cases, "],[218,"you can also customize the validation performed by the expect throws macro.\n\n"],[223,"You can customize your error validation "],[225,"to check for specific types or cases of errors, "],[228,"whether associated values or properties are correct, "],[231,"or whatever else you need to do to ensure the error your code threw "],[234,"was the right one for the job.\n\n"],[237,"In the “Meet Swift Testing” session, "],[238,"Stuart introduced the concept of required expectations. "],[243,"As a quick reminder, any regular expectation, including throwing ones, "],[247,"can be made into a required expectation.\n\n"],[251,"In cases where you’re validating an optional value, "],[254,"you can use a required expectation to document the control flow.\n\n"],[259,"It doesn’t make sense to examine a value that ended up being nil, "],[263,"so adding a required expectation lets you end your test early "],[266,"if there's nothing left to do.\n\n"],[269,"Next, let’s go over how to document known errors in your test "],[272,"using the withKnownIssue function.\n\n"],[275,"Triaging test failures is a time-consuming process. "],[279,"When you cannot immediately fix a failing test, "],[282,"or if it’s failing due to factors outside of your control, "],[285,"the failure can add noise to your test results "],[287,"that obscures real customer-facing problems.\n\n"],[291,"This test is checking that a soft serve ice cream machine "],[293,"can make an ice cream cone, "],[295,"but it looks like the machine is out of service right now "],[297,"and the test is failing as a result.\n\n"],[300,"It may be a while before the mechanic can fix the machine.\n\n"],[305,"While you're waiting for them to arrive, "],[307,"your first intuition may be to use the disabled trait on this test.\n\n"],[311,"However, withKnownIssue is a better option in this case. "],[315,"The test will continue to run and you will be notified of compilation errors.\n\n"],[320,"If the function returns an error, "],[321,"the test’s results will not count towards a test failure, "],[325,"as this failure is expected. "],[327,"Instead, the test will be surfaced as an expected failure in the results. "],[332,"When the issue is fixed and an error is no longer thrown, you'll be notified, "],[336,"and you can go ahead and remove the withKnownIssue call "],[339,"and run the test normally again.\n\n"],[342,"Your test may also perform multiple checks.\n\n"],[345,"In this case, you can just wrap the failing function in withKnownIssue "],[349,"and allow the rest of your validations to run.\n\n"],[352,"The last topic in this section I want to cover is custom test descriptions. "],[357,"In a perfect world, all of your tests pass all of the time "],[361,"and the ice cream machine is always working, of course. "],[364,"In the real world, tests do fail. "],[367,"Custom test descriptions can help you see at a glance what's going on inside a test "],[372,"and can help guide you to a solution when something is wrong. "],[376,"When working with simple enumerations, "],[378,"the default description is usually succinct and straightforward.\n\n"],[383,"However, more complex types like structures and classes "],[387,"can produce a lot more noise because their descriptions, by default, "],[390,"include a lot of extra data that may not be useful during testing.\n\n"],[396,"These values show up in Xcode with a lot of information. "],[400,"The information is accurate, "],[402,"but it can be hard to find the important bits "],[404,"that distinguish one value from another. "],[407,"In this case, you may want to give each one a concise test description "],[411,"without affecting production code.\n\n"],[414,"You can make your type conform "],[415,"to the CustomTestStringConvertible protocol "],[418,"which lets you provide a tailored, test-specific description.\n\n"],[422,"Now you'll get a much more readable "],[424,"and descriptive value in both the test navigator "],[426,"and the test report! "],[428,"We covered handling thrown errors, ending a test early with required expectations, "],[433,"handling known issues, and making test output more readable. "],[437,"Your tests are now ready to handle anything you throw at them! "],[441,"Now back to Jonathan.\n\n"],[443,"As we mentioned earlier, "],[444,"one of the challenges in preserving your code’s quality "],[447,"is covering all its edge cases: "],[449,"those bits of complex functionality "],[452,"that rarely happen in your day to day testing.\n\n"],[455,"It’s good practice to run your tests "],[457,"under various conditions to ensure you catch edge cases, "],[460,"but this previously took lots of time "],[462,"and writing a separate test for every possible variation "],[466,"is a maintenance nightmare. "],[468,"With Swift Testing, you can easily run a single test function "],[471,"with many different arguments.\n\n"],[474,"Let me show you what I mean: "],[476,"this enumeration lists various ice cream flavors "],[479,"and you can check if a particular flavor contains nuts. "],[482,"The containsNuts property needs test coverage "],[485,"for every case in the enumeration.\n\n"],[488,"Swift Testing’s parameterized testing "],[490,"makes adding that test coverage a piece of cake.\n\n"],[494,"This test function checks whether or not one of the cases in the enumeration "],[498,"vanilla, in this case contains nuts.\n\n"],[501,"You could write a separate test function for each case in the enumeration, "],[505,"but that's a lot of code. "],[507,"It would be easy to accidentally check for the wrong value "],[511,"after copying and pasting the same function so many times.\n\n"],[515,"Instead, you really only need one or two test functions here. "],[519,"After all, the logic of the tests is the same "],[521,"except for a single input value.\n\n"],[524,"And that's what a parameterized test is: "],[526,"A test that takes one or more parameters. "],[529,"When the test function runs, "],[531,"Swift Testing automatically splits it up "],[533,"into separate test cases: "],[535,"one per argument.\n\n"],[538,"These test cases are entirely independent of each other "],[541,"and are able to run in parallel. "],[543,"This means less time is needed to test them all "],[546,"all than would be needed with a for loop or separate test functions. "],[549,"Xcode supports re-running individual test cases of a test function, "],[554,"when the type of input conforms to Codable. "],[556,"This allows you to retry individual failing test cases "],[560,"without needing to re-run other test cases that have run successfully. "],[564,"Let's walk through how to parameterize our test function in more detail.\n\n"],[569,"You might start by writing a test function that loops over "],[571,"all the cases in the enumeration and tests each one. "],[575,"This function works, but we can improve it.\n\n"],[579,"One problem jumps out: "],[580,"If this test function fails for one of the values in the array, "],[584,"it will stop execution and won't test subsequent arguments. "],[587,"It may be unclear which value failed, "],[590,"and you won't get the coverage you want.\n\n"],[593,"You can move the inputs up and pass them to the test attribute "],[596,"instead of iterating over them inside the test function. "],[599,"When a collection is passed to the Test attribute for parameterization "],[603,"the testing library will pass each element in the collection, "],[606,"one, at at time, to the test function as its first and only argument. "],[610,"Then, if the test fails for one of these arguments, "],[613,"the corresponding diagnostics "],[615,"will clearly indicate which inputs need your attention.\n\n"],[618,"You're almost done! "],[620,"If you add a second function that tests those flavors that do contain nuts, "],[624,"you'll have 100% code coverage for this enumeration. "],[627,"And it's easy to add new test cases if you expand the enumeration in the future.\n\n"],[633,"That example looked at the cases of an enumeration, "],[636,"but parameterized test functions can also accept many other kinds of input.\n\n"],[640,"Any sendable collection, including arrays, dictionaries, ranges, and more "],[645,"can be passed to the test attribute.\n\n"],[648,"Test Cases along with their arguments are displayed in both the test navigator "],[652,"where each argument will get its own run button, and a test report, "],[656,"where you’ll get a rich information view for failed parameterized tests. "],[660,"So far, you've learned how to write parameterized tests with 1 input, "],[664,"but what if you need to pass more? "],[667,"Test functions in Swift Testing can accept multiple inputs, "],[671,"and you can add another argument to this test "],[673,"by simply appending it after the first argument.\n\n"],[676,"Every element from the first collection is passed "],[678,"as the first argument to the test function, "],[681,"and every element from the second collection "],[682,"is passed as the second argument. "],[685,"All combinations of elements from these two collections are automatically tested.\n\n"],[690,"Being able to test every combination in a single test function "],[694,"is a powerful way to improve your test coverage! "],[697,"To help visualize just how powerful, let’s consider two arrays of arguments, "],[702,"raw ingredients and the foods you can make with them.\n\n"],[705,"A test function with two arguments will test every possible combination, "],[708,"sixteen in total. "],[710,"You might find yourself taste testing some strange pairings. "],[714,"I like egg salad and omurice as much as the next engineer, "],[717,"but help me out here what are lettuce fries? "],[721,"And that was just four values in each array. "],[723,"As you add more inputs to the two sets, "],[726,"the number of test cases will grow and grow and grow, exponentially! "],[731,"To help control this exponential growth, "],[734,"test functions accept a maximum of two collections. "],[737,"You can also use the Swift standard library's zip function "],[740,"to match up pairs of inputs that should go together.\n\n"],[744,"Instead of testing every combination of raw ingredient and final dish. "],[748,"Call zip and they'll be paired up.\n\n"],[751,"Zip will produce a sequence of tuples, "],[753,"where each element from your first collection "],[755,"is paired with its corresponding element "],[757,"in your second collection, and nothing else. "],[760,"Now you've got the tools you need "],[761,"to expand your test coverage with parameterized testing! "],[764,"Back to Dorothy to talk about organizing test. "],[768,"With all these new features to help you write more tests, "],[771,"you need strategies to manage them. "],[773,"Let’s go over the tools Swift Testing provides to organize your tests.\n\n"],[778,"To recap, suites are types containing test functions.\n\n"],[782,"Their functionality can be documented with traits, such as, a display name. "],[787,"New in Swift Testing, suites can now contain other suites "],[791,"to give you more flexibility in organizing tests. "],[794,"This is a pretty, sweet set of tests but it’s not organized very clearly. "],[799,"The test suite includes tests "],[800,"for warm desserts, and tests for cold desserts.\n\n"],[804,"By adding sub suites, you can reflect this organization in the tests themselves, "],[808,"and make relationships between these groups of tests, more obvious.\n\n"],[813,"Tags are another trait that help you organize your tests. "],[816,"A complex package or project may contain hundreds or thousands of tests and suites.\n\n"],[821,"You probably have multiple test suites covering different parts of your code. "],[826,"Although they're not directly connected, "],[828,"some subset of your tests may share common characteristics.\n\n"],[832,"In this example, some tests involve foods that are caffeinated, "],[836,"and some involve foods that are chocolatey. "],[839,"In this case, tags can help you associate these tests across the two suites.\n\n"],[844,"Keep in mind: Tags are not a replacement for test suites. "],[847,"Suites impose structure on test functions at the source level, "],[850,"while tags help you associate tests from different files, "],[854,"suites and targets that share something in common.\n\n"],[857,"That's tags in a nutshell but how do you declare a tag and add it to a test? "],[863,"All of these drinks contain caffeine, as does any espresso brownie worth eating. "],[868,"You can create a caffeinated tag "],[869,"to relate these tests even though they exist in separate suites.\n\n"],[874,"First, extend the Tag type, "],[875,"and declare a static variable with the name caffeinated. "],[879,"The variable needs to be an instance of Tag. "],[882,"And the secret ingredient: "],[884,"Add the tag attribute to the variable to make it usable as a tag in your tests.\n\n"],[890,"Now that you've created the tag, you can add it to these tests. "],[894,"You can add it at the suite level for DrinkTests "],[896,"because all the drinks used in those tests are caffeinated, "],[899,"and tests inherit tags from their suites.\n\n"],[902,"Then, you can add it to espressoBrownieTexture. "],[906,"It's the only caffeinated food in DessertTests, "],[908,"so you wouldn't want to add it to the entire DessertTests suite.\n\n"],[913,"Suites and tests can also have multiple tags. "],[916,"For example, while mocha and espresso brownies are both caffeinated, "],[921,"they're also both made with chocolate! "],[924,"You can create a chocolatey tag and add it to those two tests.\n\n"],[928,"Tests are grouped together by tags in the test navigator "],[931,"and allow you to run tests that have specific tags. "],[934,"Let's take a tour and see how you can use your tags in Xcode 16. "],[939,"The test navigator has several new features "],[941,"to help you work with tagged tests. "],[943,"By default, the navigator shows tests "],[946,"organized by their location in your source code. "],[949,"I've been busy perfecting my top-secret hot sauce recipe, "],[952,"and I want to improve my test coverage for code that uses it. "],[955,"These are the tests I've already written.\n\n"],[958,"I'm going to use the filter field at the bottom of the test navigator "],[961,"to find tests related to my hot sauce. "],[964,"As I start typing, Xcode will suggest tags "],[966,"based on the ones available in my project.\n\n"],[969,"Xcode is now surfacing a few tag suggestions, like seasonal, "],[973,"spicy, and street food. "],[975,"I’ll continue typing to narrow down my results.\n\n"],[979,"By default, the filter field matches the tests’ display and function names. "],[983,"That’s why tests like Spice blend in gingerbread cookies "],[986,"and Spinach and artichoke dip ratio are showing up.\n\n"],[990,"Xcode is also suggesting tests "],[992,"that do not have any words highlighted in their names. "],[995,"That's because they have tags that match what I've typed.\n\n"],[999,"When I click spicy in the suggestions popover, "],[1001,"The Test Navigator will convert what I typed into a tag filter "],[1005,"which will remove all tests that don’t have that tag. "],[1008,"Now the test navigator is showing me only tests with the spicy tag.\n\n"],[1012,"The test navigator can also group tests by their tags. "],[1016,"I can switch to this view "],[1017,"by clicking on the tag icon at the top of the test navigator. "],[1021,"I'll remove the tag filter "],[1022,"so all the tags in my project will show up in the results. "],[1026,"This view gives me a convenient way to run my tests. "],[1029,"Like the hierarchy view, "],[1031,"I can click the play button beside any tag to run all tests with this tag.\n\n"],[1036,"As I’m developing, "],[1037,"I can run my hot sauce-related tests and get quick feedback on my changes. "],[1042,"In addition to running these tests manually "],[1044,"you can save these tag preferences to your test plan "],[1047,"using the redesigned test plan editor! "],[1050,"I've created a new test plan that includes a core set of reliable tests "],[1054,"so I can quickly catch any bugs I might introduce as I make changes. "],[1058,"This test plan includes all of my test targets. "],[1061,"I can switch to the new test plan by selecting its name, Core Food, "],[1065,"from the list of test plans in the test navigator. "],[1069,"Then, I'll open the test plan editor "],[1070,"by clicking its name directly in the test navigator.\n\n"],[1074,"I’ll expand my unit test target to view all my tests.\n\n"],[1078,"I'll also hide the navigator to give myself a bit more room to look around.\n\n"],[1082,"As a reminder: a test plan can reference one or more test targets, "],[1086,"and the test plan editor lets you organize tests across all of those targets.\n\n"],[1091,"The tags for each suite and tests are displayed in the right-hand column.\n\n"],[1096,"I can choose which tests to include or exclude "],[1098,"by specifying tags in these fields at the top of the test plan editor. "],[1103,"Suppose I want to update this test plan to run all my core tests "],[1106,"except for those with the seasonal tag. "],[1109,"Those tests cover code that is only expected "],[1111,"to work at certain times of the year, "],[1113,"so I don't want them to always run.\n\n"],[1116,"I can exclude tests with the seasonal tag "],[1118,"by adding that tag in the exclude field.\n\n"],[1121,"The test plan preview automatically updates to match my changes. "],[1125,"Tags that are currently active in the include and exclude fields "],[1129,"will be highlighted in purple. "],[1131,"Tags that are excluded from the test plan will be crossed out.\n\n"],[1135,"I'll add another tag to the exclude field, "],[1137,"and that will give me some additional filtering options. "],[1141,"When my test plan is filtered by more than one tag, "],[1143,"Xcode gives me the option to match either all tags or any tags. "],[1147,"All tags is the default.\n\n"],[1150,"In this case, I'll use any tags because I want to exclude all tests "],[1154,"tests that have the seasonal or the unreleased tag. "],[1157,"Now both tags are highlighted in purple, "],[1160,"and both are crossed out "],[1161,"because they’re being actively excluded from my test plan.\n\n"],[1165,"Tags are also a useful tool "],[1166,"that helps you analyze your results across entire test targets. "],[1170,"This is the test report that was generated "],[1172,"after running the test plan we just created. "],[1175,"There are quite a few failures, "],[1177,"so let’s investigate how the test report can help us "],[1180,"fix failures faster with tags.\n\n"],[1183,"Let’s explore the tests outline screen.\n\n"],[1186,"Tags now appear in the outline, next to their corresponding suites and tests.\n\n"],[1191,"We can narrow down the results by using the tags filter. "],[1195,"But because I have so many failures, "],[1196,"it will be tedious to look through each one.\n\n"],[1200,"Navigating to the all insights screen, "],[1202,"there’s a new section for distribution insights, "],[1205,"which surfaces patterns in test failures "],[1207,"that have common run destinations, tags, or bugs. "],[1211,"This insight is interesting. "],[1213,"All of the tests with the spicy tag failed.\n\n"],[1216,"We can navigate to the details screen by double clicking on the insight row.\n\n"],[1221,"All the associated failing tests with their failure messages "],[1224,"appear in this screen.\n\n"],[1226,"I recently modified the chili pepper that we use in our secret hot sauce, "],[1230,"so that could be the reason all the spicy tests are failing. "],[1234,"I’ll review my changes and fix my tests.\n\n"],[1237,"Xcode Cloud has also been updated to support Swift Testing.\n\n"],[1242,"Just like in Xcode, you can view the results of your test suites "],[1245,"in the Xcode Cloud tab of App Store Connect. "],[1248,"This includes details about the traits that have been defined in your tests. "],[1253,"When you organize and relate your tests, "],[1255,"Xcode can help you gain insight into problems affecting them. "],[1258,"Suites and tags make large collections of tests more efficient to navigate "],[1263,"and easier to manage. "],[1265,"Back to Jonathan to talk about running test in parallel.\n\n"],[1269,"Now that you have a sizable and manageable test suite, "],[1272,"it's time to consider how testing in parallel "],[1274,"can keep your tests passing quickly "],[1277,"and how to ensure they run reliably in a concurrent environment. "],[1280,"Parallel testing is enabled by default in Swift Testing, "],[1283,"so you can start taking advantage of these features with no extra code.\n\n"],[1288,"For the first time, you can run parallel tests on all physical devices, "],[1292,"bringing all these great advantages to even more tests! "],[1296,"Let’s begin by going over the basics of parallel testing. "],[1299,"Tests run one after another in serial testing. "],[1303,"If you've used XCTest before, this is how it runs tests by default.\n\n"],[1308,"This is in contrast to parallel testing, where tests execute concurrently. "],[1313,"You gain several advantages when your tests run in parallel.\n\n"],[1317,"First, execution time will be reduced, "],[1319,"which is crucial in CI where every minute counts. "],[1323,"This also means a faster turnaround to get your results. "],[1326,"Swift Testing runs test functions in parallel by default, "],[1330,"regardless of whether they are synchronous or asynchronous. "],[1333,"This is a notable difference from XCTest, "],[1336,"which only supports parallelization using multiple processes, "],[1339,"each running one test at a time.\n\n"],[1342,"Test functions can be isolated to a global actor like MainActor when needed. "],[1347,"Next, the order in which your tests run is randomized. "],[1351,"This helps surface hidden dependencies between tests "],[1354,"and exposes areas where you may need to make adjustments.\n\n"],[1358,"Let's look at an example. "],[1359,"I have two tests: in the first one, I bake a cupcake, "],[1362,"and in the second one I eat it.\n\n"],[1365,"If these tests always run in order and run one after the other, "],[1368,"then I'll always have a cupcake ready for the second test "],[1371,"because it was baked in the first test. "],[1373,"That wasn't intentional! "],[1375,"If the tests run in parallel, "],[1377,"then the second test's dependency on the first will be exposed at runtime "],[1381,"and I'll be able to fix it. "],[1383,"If you’re converting older test code, "],[1384,"some of those dependencies may already be baked in.\n\n"],[1388,"Swift 6 will be able to help you find some of the problems with your existing code "],[1392,"as you rewrite it, "],[1393,"but others will be harder to find. "],[1395,"As your first step, you may just want to convert your code to Swift Testing "],[1399,"and come back to address those problems later.\n\n"],[1402,"You may not be able to fix them all just yet, "],[1404,"which is where the .serialized trait can help.\n\n"],[1407,"The .serialized trait can be added to a test suite "],[1410,"to indicate that its tests need to be run serially.\n\n"],[1413,"These tests will lose the advantages we just discussed, "],[1416,"so you should first consider refactoring your test code, "],[1419,"whenever possible, to run in parallel.\n\n"],[1422,".serialized can also be applied to a parameterized test function "],[1425,"to ensure its test cases run one at a time.\n\n"],[1428,"If applied to a suite that contains another suite, "],[1431,"it’s automatically inherited and you don’t need to add it twice.\n\n"],[1435,"Tests in a suite with the .serialized trait will run one after another. "],[1439,"However, Swift is still free to run other unrelated tests "],[1443,"in parallel with these serialized tests, "],[1445,"so you can still get parallel performance. "],[1448,"If necessary, you can run tests serially "],[1451,"but we recommend refactoring your tests so they can run in parallel.\n\n"],[1455,"Parallel testing is on by default when you use Swift Testing "],[1459,"and will let your tests run as fast as possible. "],[1462,"And Swift 6 can help you find issues with your tests "],[1464,"that prevent them from running in parallel.\n\n"],[1467,"Next, we’ll show you techniques for waiting on asynchronous conditions "],[1470,"with Swift Testing.\n\n"],[1472,"When writing concurrent test code, you can use the same concurrency features in Swift "],[1476,"as you would in your production code.\n\n"],[1479,"await works exactly the same way and will suspend a test "],[1482,"allowing other test code to keep the CPU busy while work is pending.\n\n"],[1487,"Some code, especially older code written in C or Objective-C, "],[1491,"uses completion handlers to signal the end of an asynchronous operation.\n\n"],[1495,"This code will run after the test function returns, "],[1498,"and you won't be able to verify the function succeeded.\n\n"],[1502,"For most completion handlers, Swift provides an async overload "],[1505,"automatically that you can use instead.\n\n"],[1508,"If the code you're testing uses a completion handler "],[1511,"and an async overload is NOT available, "],[1513,"you can instead use withCheckedContinuation "],[1516,"or withCheckedThrowingContinuation "],[1519,"to convert it to an expression that can be awaited.\n\n"],[1522,"For more information about continuations in Swift, "],[1525,"watch \"Meet async/await in Swift\".\n\n"],[1528,"Another kind of callback is an event handler that may fire more than once. "],[1533,"This version of the eat function calls its callback once for each cookie "],[1537,"instead of at the end of the whole meal.\n\n"],[1540,"However, trying to count the number of cookies eaten with a variable "],[1543,"will result in a concurrency error in Swift 6 "],[1546,"because it's unsafe to set a variable this way.\n\n"],[1550,"If the code you’re testing may invoke a callback more than once "],[1553,"and you need to test how many times it is called, "],[1555,"you can use a confirmation instead.\n\n"],[1558,"By default, a confirmation is expected to occur exactly once "],[1562,"but you can specify a different expected count. "],[1565,"I'm baking and eating 10 delicious cookies, "],[1568,"so I expect this event will occur 10 times. "],[1571,"You can also specify 0 if the confirmation should never occur during testing.\n\n"],[1576,"Swift concurrency is a powerful tool in your production code and in your tests. "],[1581,"Get faster results by running your tests in parallel, "],[1584,"and use async/await, continuations, and confirmations "],[1587,"to ensure your test code runs correctly in a concurrent environment. "],[1592,"In this session, you learned how Swift Testing can improve your testing workflow. "],[1596,"We’ve covered a large range of topics, so let’s do a quick recap! "],[1600,"To start, we looked at how Swift Testing’s APIs help you write expressive tests. "],[1606,"With parameterization, you can exercise many different cases with a single test.\n\n"],[1612,"Tools such as suites and tags help you organize and document your test code.\n\n"],[1618,"And finally, testing in parallel can reduce the time it takes to run your tests "],[1622,"and may help identify dependencies between them. "],[1626,"Thanks for tuning in "],[1627,"Happy testing!"]]}}