How Professional QA Implements A Robust CI/CD Pipeline?

Hamidakhtar56 - Oct 6 '22 - - Dev Community

The obsolete conventional methods of software developments were not taking over the escalated market trends, and those methods lacked solutions for the increased demand of quick software release that introduced the “Continuous Integration (CI) and Continuous Delivery (CD)”. Along with CI/CD, you need to have that kind of technical capability where developers adapt to the shortened delivery cycles and automation processes. Keeping up with the acceleration of change in the testing world, you need to deepen, broaden, and make a strong network with other QA professionals also. Easier said than done, I know! I have often observed the struggle involved in implementing a CI/CD pipeline release cycles, improper resource management, unrealistic ETAs, hesitation involved in task management from a QA manager point of view. Which is why, I intend to talk about the rise of CI/CD pipeline, common challenges, and actionable insights every QA should follow, to cruise swiftly & safely through every release using a CI/CD pipeline.

Why CI/CD Pipeline Became An Obvious Choice To A Majority Of Organizations?

Sooner or later, by now, testers went on shifting towards Continuous Delivery in projects and organizations. The teams opted for the CI/CD pipeline to take advantage of the perceived benefits of a quick release build, that was at the push of a button. Businesses need faster feedback, consequently vastly improved time to market. This led to an increase in worldwide adoption of CI/CD pipeline. In personal experience, CI/CD pipeline left an impact on how I used to approach my testing as it helped my team to accelerate the go-to-market launch.

My developer friends had little hunger for testing approaches, especially the lengthy testing phases that were never found to keep up with the pace of delivery. Continuous Delivery becomes right up to developers’ alley when they get rapid feedback on their code. The moment they check in, they get the signal if they mistakenly introduced some kind of issues within the build pipeline comprising different layers of testing. Without even test automation, you have a tendency to know the feedback from live users — a direct connection from your customer base. Developers never cripple with fast feedback and hence enhance the production. Build pipeline reduces the waiting time expected for integration and release testing. That means that everything happens at one go: write code — test locally — review — merge — integration — and into the tester hands. One of the key parts is test automation where a company can focus on continuous integration and continuous delivery of the software. A single click can land the executable to an environment, that is local, test or production. Best practices in CI/CD pipeline can deliver the product in high quality.

Importance of CI/CD pipeline became evident with time demanding for agile, kanban and other latest SDLC approaches. But how do we as a professional QA should go about managing ourselves in a CI/CD pipeline. Let’s find out.

Rational Steps Every QA Should Note For A Successful CI/CD Pipeline

In the CI/CD pipeline, a technical part could be a trap for the testers. Basically, their duty entails more than that: all the attention to the requirement, practices, products, and processes. Should you start working in a Continuous Delivery environment — Contemplate x 10 times! Think about:

  • Whether the team is heading in the right direction?

  • If all the business requirements have transformed into executable specifications?

  • As a QA tester in what way you are going to contribute in terms of scenarios, acceptance criteria, and examples.

  • Do you think already floating processes have room for improvement? Are you able to detect the waste and remove that waste finally?

  • Your experience about non-functional testing, performance, accessibility, and security etc.

  • Cross browser testing to ensure your changes looking good to the audience who is viewing your web-application from different browsers, browser versions, devices, and operating systems.

  • Calculating your ROI on test automation with Selenium for automated cross browser testing.

  • The difference between cross browser testing & responsive testing. Both the testing practices are often misinterpreted as one & the same. However, they are not!

  • Version Control, being a cornerstone of CI/CD pipeline enable developers to collaborate on a shared codebase. Version control is an absolute must and a great companion of CD. You have the undo functionality in version control system means rollbacks to the previous release. In addition, configuration, databases, scripts, documentation can be tracked throughout history.

  • Data and configuration required across all the staging environments. Keep in mind, the 13 reasons why the staging environment is failing for your organization.

  • Creating automated stable tests across the entire application with test frameworks and automated tools

  • A deep insight: no code or feature remain untested that can further decrease in speed consequently; holding back your team to release the software at times.

  • A good tracking mechanism to maintain the effectiveness of the regression test suite clearly outline a process and ensuring only useful tests are added to the test suite, having a consolidated view of all the quality activities as you keep regression defects in check.

  • Automatic code commits, test suites, and test environment produces immediate feedback, and when you turn to CI/CD pipeline, it automatically resolves issues like version control, or when coders would write unit tests which are often found tough to turn into a workflow. Upholding the desired level is the key point of Quality assurance. QA means the inclusion of growing ideas and long-term maintenance and three important points that can be brought to the surface are: Testing, Delivery, and Optimization.

  • How other QA member would write test packages to run them automatically during every successive build? Maintaining them within a CI system makes the test suites more organized and easily accessible.

  • You need a Continuous Integration Server to monitor the main repository where you will be running the automated tests for newly submitted commits.

  • Specific roles of developers who would deal with merging the changes as often as possible.

  • Development lifecycle starts with checklists or playbooks comprising the tasks that happen to be performed manually. Later on, those tasks could move to automation with scripts and tools. With that, you ensure tasks are repeatable as a team member can run the script if the checklist needs to be run again. Moreover, you run playbook scripts consistently between environments, you increase the reliability like a script for deploying code mirror the production environment.

QA doesn’t limit itself within the fundamental aspects of the why & how to create a front-end website testing plan, in fact, it adds value to the organization. As much as you tend to optimize QA, the greater the chances of a faster product cycle increases. And with fast feedback loops, you can outpace the result.

Thorough testing plays an important and crucial role in the success of a software product. Always think twice, thrice about the test cases to automate, and to get the most out of it, start as early as possible. Starting out from day one gradually build your automated suite that can detect bugs at a much cheaper price rather that you find the same issues in later stages of your cycle. Squeezing test in at the end is a lot more problem so keep on figuring out the following:

  • How frequently you are going to repeat the scenario?

  • The length of the process.

  • Enlist all the recurring test cases that gets executed for multiple builds.

  • Check the people and resources dependencies involved and any shortfall or delay that might cause due to them.

  • If you are skipping the automation at any place, ensure it will not turn out to be an error-prone process.

Automate Cypress testing and perform browser automation testing with LambdaTest. Our cloud infrastructure has 3000+ desktop & mobile environments. Try for free!

Most Common Challenges For Every CI/CD Pipeline

  • Developers devote 20–40% of dedicated time to debugging. That means, spending an increasing percentage on debugging software rather than building new features results in reverse outcome, and thus loss of productivity, uncontrolled spending, and employee churn.

  • Even the most thorough testing, staging, and QA process could allow slipping errors through the cracks, so always be ready to face unexpected, or disruption, and breaking the code often in CI/CD pipeline.

  • Engineering teams face the challenges even after the code is deployed as the cycle becomes more uncontrolled when you don’t add automation to your monitoring process. Outdated production monitoring practices often stall a CI/CD process, and an informed production error handling strategy should come in place to mitigate the associated risks.

  • Error-prone tasks, addressed at a time could prevent enough loss of energy like a painful chore might consume more than 20 minutes and multiply by 5 times for a week, would compound to a 100 painful minutes. So for a healthy dose, address the chore and optimize at the initial stage and thus preventing a painful time altogether. On this front, do the hardest part first that will further analyze and identify weaknesses in the organizational process. The procrastinated task is an indicator to an area of improvement so a team should pursue or keep them at the forefront to resolve it at the earliest.

  • Website business has nothing to do if an app is working solely on a developer’s machine. Overall business goal and empathy should be the key responsibility of each team member. CI/CD pipeline is entirely meant to ship code changes to the website for an end user’s convenience. So when you “done”, ensure the entirety of the team’s responsibility and contribution is complete.

Actionable Insights For Every QA To Implement A Robust CI/CD Pipeline

Other than the rational thought process, as a professional QA, you are responsible for every minute change that takes place in the production environment. Slacking off on any release cycle could lead to a flood of outages. Which is why it becomes imperative to keep a checklist on all the actionable insights one needs to take care of for ensuring a successful CI/CD pipeline.

Test Automation With Selenium For Automated Cross Browser Testing

Your website is the identity of your business on the internet, and it would be terrible if it starts looking weird on some browsers and devices after your recent code changes in production through CI/CD pipeline. Cross browser testing is a process to measure how well a website would fare against different rendering engines of different browsers and browser versions.
Test automation with Selenium can help pace your things up a lot faster, resulting in the faster go-to-market launch with the help of parallel testing in Selenium.

LambdaTest provides you with a cloud-based cross browser testing tool which offers a Selenium Grid of more than 3000 real browsers along with LambdaTest integration to numerous CI/CD tools such as Jenkins, Travis CI, CircleCI, and more.

Exploratory & Automation Testing

Our regular readers would know our main emphasis lies in the ability to test at the speed. Maintaining the quality and what value a QA holds for every CI/CD pipeline, I am going to share with you the experience of how we focussed on the testing programs to adjust with CI and agile approaches to development. Exploratory testing is pivotal for a successful CI/CD pipeline, and you can blend it with automation so as to make a growth in testing and business as well. Learn more from Exploratory Testing: It is all about discovery!

All facets of the company in QA needs to be determined when you start integrating QA in the process. Once you have known what needs to be automated, go for it & automate. Functional testing can’t sit in automated testing place because you don’t know what you could program next. In that type of scenario, we blended it with automated test creation depending on the exploratory bugs. Now, the build is filtered after the functional exploratory testing for automating the testing of remaining bugs. Your cognitive skills in functional exploratory testing bring you to a point when you start assembling all the features to test and turn the QA into a gatekeeper for release. Developers start releasing the build to CI/CD servers for the QA department who conducts the test before release using a sturdy CI/CD pipeline.

Automate Cypress cloud tests and perform browser automation testing with LambdaTest for free!

Functional and UI testing

Functional and UI testing both are repeated at least once per day, and require 2–3 hours for a medium-sized application. In the case of test automation with Selenium, there is no need to update the automation script frequently, but UI often gets modified, thus require frequent script changes. Both depend on multiple dependencies and both are error-prone and when we have to decide which one to prioritize, I would say bring functional testing before UI testing that makes the best use of resources.

Automated Regression Testing

Regression Testing is used when a developer makes changes to functionality or repairs a bug. The CI system serves as a QA tool for automated regression testing suites for long-standing products, working well for Agile development where teams are supposed to deploy a product at least weekly and have shorter deadlines to accommodate manual regression testing. Another advantage is you can use the infrastructure for your future products and hence accelerating test automation. CI automatically adds new test cases when a new defect is found. The CI builds upon itself a substantial regression test suite running automatically against the new code.

With LambdaTest, you can perform test automation with Selenium in parallel for executing your automated regression test suites over different browsers, browser versions, simultaneously.

Aligning the Agile Testers & Developers

I believe it will always be unfortunate if the quality is portrayed as an after-the-fact, meaning you first underline the requirements and then design, coding, and finally shifting the gears towards quality and say: “let us bring some testers”. Testing or the whole quality is absolutely is an important aspect when you have to ship your products as early as in a week or month. Agile methodologies break down the software development into user stories (smaller tasks). This results in faster feedback, and go-to-market launch. Helping you develop better web-apps, faster. With CI/CD pipeline you can validate your web-application on a more frequent basis. However, automating all facets of building, integrating, testing, and deploying software mitigate risks. And if you see it in the context of Agile vs Waterfall methodology, Agile rapidly leaves behind waterfall methodology by supporting a process in which requirements are expected to change and evolve frequently. While developing websites with frequent overhauls, keeping pace with technology landscape, customer requirements, agile addresses the needs of developers with the selection of effective automation processes. Check out our read on “What I Learned While Moving From Waterfall To Agile Testing?

Don’t Start Test Automation With Selenium If You Are Clueless!

Sure, there are benefits to test automation with Selenium. However, without a strategy, you could end up using a complex code for a simple code testing. It is important to analyze how different parts can be automated. Undertaking an automation initiative shall not be overlooked but the strategy shall help us meet our goals. I always recommended isolated unit tests which are supported by every language. Fast running unit tests boost the confidence level and ensure the correctness of code in mere seconds. If unit tests fail, no need to move further. Pass unit test implies components are doing well and application is building up all according to the customer expectations. Yes, BDD is the best practices for writing better-automated tests. Here are 8 actionable insights for writing better automation code.

Selecting The Right Automation Testing Tool Based On Your Project Requirements

You can see the widespread market of the automated testing tools, and the important thing is to select the right testing tool that suits your overall requirement: It should support platform and technology like C#, Java, or .Net applications and using which operating systems? Furthermore, take your decision based on whether you need to test web application, or mobile application: Android or iOS or both the operating system. For example, if you wish to perform automated cross browser testing, then Selenium being a reliable open-source comes as the first choice. However, there are still some limitations to it, if you opt for on-premise test automation with Selenium. You are limited to the number of browsers on which you can test in parallel using Selenium Grid. Also, the Selenium Grid to run say 4–8 parallel test sessions would need a very solid hardware requirement. An optimal solution for that would be considered as a cloud-based cross browser compatibility testing tool such as LambdaTest.

LambdaTest offers a Selenium Grid which is compatible with every framework and language that supports Selenium. You get to perform test automation with Selenium on-cloud, at scale. You also get integrations to numerous third-party project-management tool, CI CD tool, along with their Chrome Extension & their WordPress Plugin.

LambdaTest also offers Open Selenium API to help you extract your test details, test reports of your test automation Selenium script execution from LambdaTest platform to your preferred system, without logging into LambdaTest.

Incorporate Continuous Testing In Your CI/CD Pipeline

Continuous testing is a process of evaluating an E2E evaluation of your web-app using a comprehensive range of automated test suites. It ensures quick circulation around feedbacks and upcoming sprints.

CI systems are not restricted to code-level unit tests and can even perform integration testing on interdependent platforms at once. Don’t use integration testing to test business logic, that’s what unit tests are for. CI system run unit tests very fast for every build. Integration testing takes much longer to run whereas unit tests target basic correctness of the code. Units tests should flush out all the bugs of business logic.

Incorporating continuous testing in your CI/CD pipeline, and empower your QA team with faster evaluation using test automation and feedback. Check out our readers to know more about implementing continuous testing in DevOps like a pro.

This Cypress test automation tutorial will help you learn the benefits of Cypress automation, and how to install Cypress and execute Cypress automation testing over scores of browsers and operating systems online.

Introduce Fault Injection Testing For Better Test Coverage Of Your CI/CD Pipeline

As the name suggests, Fault Injection Testing is where you intentionally push faults into your code for enhancing the sturdiness of a web-application, along with the test coverage. Introduce the fault injection testing as a standard part of a review and when your processes and practices get mature, it will ensure the web-application’s resilience. Indeed it is a good practice when you are able to analyze the results of bugs or errors infused in advance before they appear in the production. Though you can conduct the Fault injection tests manually, however, there are tools available for it as well.

Don’t Leave Failing Tests Unattended

A certain level of discipline is necessary for the team that stops to skip any failing test & when you are holding it temporary (i.e. throw SkipException) or using a tool to mute, place the proper comment for the time being and ensure it does not remain unattended or ignored a bit longer in the configuration. A single build does not contain a lot of changes, so reviewing the build time to time can locate the tests. In fact, Reviewing builds with certain changes helps you in identifying any broken test. And the CI/CD pipeline must be stable with a trunk that tells you if a build has failed, either by notification via email or IM. TeamCity provides numerous features and one of them letting you know — who is taking care of failing test.

LambdaTest offers integration with TeamCity to help you fast-track automated cross browser testing on every commit made along with your CI/CD pipeline.

Keep Load Clashes In Mind

CI/CD pipeline incorporates testing to ensure the delivered build is stable and bug-free. While adhering to CI/CD pipeline, reporting of issues is the key factor. A full report furnishes the details on how the tests were run and if anyone failed, the reason behind it. Have you ever tested a web server for performance? Which tool did you use? I would reckon 60% chances are it was JMeter. This tool simulates real-user behaviors and gives sophisticated reports.

The best thing is, Jmeter works with selenium Grid to check the software performance under the multiple and concurrent user traffic. Maven, Jenkins, and Selenium can be used together to create good end-to-end reports, create APPDEX(Application Performance Index), and the documented behavior of the application by hitting browsers concurrently. I have included the performance testing in the talk so that you can mark it since the beginning to avoid unexpected load clashes.

A Meaningful Dashboard

Indeed testing earlier and faster is cumbersome without automation. One of the major challenges for any CI/CD pipeline lies with the collaboration among various teams or departments such as DevOps, QA, Security team, etc. working to bring a common web-application in the market. You would require a place or rather a dashboard that is transparent to all and relays meaningful and organized information. CI/CD tools like Jenkins, Git, and Jira enables teams to coordinate seamlessly and a meaningful dashboard which was customized by assessing what data everyone wants will matter most to your DevOps project. I would recommend adding Feature gadgets configured from different data sources of DevOps tools to help in managing your CI/CD pipeline. A “Feature” gadget breaks down the stories and lets you know which stories are done or in progress yet. A way to drill down deeper to nurture the adoption of a DevOps culture. Different members have different priorities, so you need to perform a progressive assessment when you plan to design a dashboard. It is slightly tricky to make a useful dashboard for CI/CD pipeline, and when everyone consent is important. Nonetheless, it is crucial too!

For instance, if you are performing test automation with Selenium using LambdaTest a cross browser testing cloud, you get an intuitive dashboard which displays test details around timestamps of test case execution, metadata, command-by-command screenshots, Selenium logs, network logs, command logs, video logs which represents recording of your test execution and more.

Go For A Unique Naming Convention To Ensure A UI Resistant CI/CD Pipeline

Automated tools are property-based testing tools that help to locate and identify an object. Depending on the location coordinates, the tool may fail if it finds the change in control caption or location. The UI of any web-application is an ever-changing part. You will have different developers working on different requirements, time over time. Now, you wouldn’t want these developers to go ahead without following a standard naming convention. As a property-based testing tool will fail to pin-point an object if the naming is repetitive. This would become a hassle later on as you would have to rename the old names for your entire web-application. Hence, provide unique names for your controls that will ensure automated tests won’t need changes itself and are resistant to UI changes.

Continuous Deployment & Continuous Delivery, Know The Difference!

If the build is deployed immediately after some modification made in the code base, could be annoying for the users. The key for continuous delivery is to keep the codebase at deployable state, and not practicing continuous deployment doesn’t mean you are not practicing Continuous Delivery. Continuous delivery is a small build cycle and having short sprints in the cycle gives quicker turn times to detect bugs and hence quick fixing of those bugs. Overall, it gives a stable code base early on. This is a preferred method allowing the team to address issues immediately, and not later on when you plan to release the codebase. It offers total control over product rollout, risk factors, and functionality.

User Experience Testing

In user experience testing, you collect qualitative and quantitative data from the users and once your application is assembled, testing objectives turn into the user experience which can be achieved by combining load testing and cross-browser compatibility or mobile testing tools. End-to-end testing is important and also unnecessary extending the length of end-to-end testing needs to be avoided. As it could affect productivity, if you keep on executing more tests, therefore stay focused on right and important things.

“If you want a great site, you’ve got to test. After you’ve worked on a site for even a few weeks, you can’t see it freshly anymore. You know too much. The only way to find out if it really works is to test it.” — Steve Krug — Don’t Make Me Think

Smoke Tests

Smoke testing monitor the system and verify whether the most important features or core functionalities are working. The smoke test allows you to do rapid regression testing of major functionalities indeed, determining if the product is ready for testing to prevent further waste of time and resources.

Automate Deliverable & Deployment

Automatically generated deliverables remain available to a wider audience and the credit goes to automation. Alpha and beta testing can be shifted to more stages of development. A CI/CD pipeline system enables automated deployment with system tests deployment scripts, it helps to ensure the absence of kinks while moving to other environments.

Documentation Is The Foundation Of A Sturdy CI/CD Pipeline

In automated unit testing, quality of code can be protected to document standards, thereby helping to improve the quality of the next solutions. Automated unit tests can also work as self-documenting code; maintaining code plays a vital role in the development of software. Shortage of documentation or difficulty in understanding the code should be dealt with — as the programmers may be reluctant or dislike writing documentation. Having a document that contains all the information that the code is doing should mitigate the unnecessary cost of software maintenance.

Unhandled Interruptions Are Bound To Cause A Test Failure

Platform security, adding failover logic into the framework during the automated tests, logging any kind of interruption, all these cumulative efforts could reduce or avoid interruptions at large extent, leading to thorough validation using test automation. Legitimate bugs or retry attempts may also fail to handle interruptions, therefore a safer approach is “fail the test” in those conditions.

If you are performing test automation with Selenium Grid offered by LambdaTest, then you can mark an automated test as either pass or fail, based on your requirement.

Resource Management Can Help Your Cruise A Long Way

Writing automated script should be assigned to an expert possessing extensive experience of scripting language provided by the automated testing tool. Contrary to that, if one is not versed in writing automated test scripts, maybe that QA engineer is better at writing test cases and can be pulled up when there is no need for in-depth knowledge of scripting languages. Once an automated script is designed you can provide a knowledge transition to automation tester who are less experienced and make them responsible for daily evaluation through that script. Meanwhile, the experienced QA in your team could come up with more out of the box test cases.

Continuous Improvement

The CI/CD pipeline does not end at deployment. The feedback loop, being the heart of CD, indicates an additional phase of monitoring of the deployment. The phase will again use the automated tools to determine the impact of deployment on the end-user. You keep an eye on an obvious metric like business revenue alone with some more granular metrics like engagement time and user conversion rates to observe the correlation.

All team members on the same page

All the team members should be informed consistently, even if they are not sitting on your CI server. Automation notifications can fetch the inaccessible team members of QA in loop helping to keep higher quality overall. Tight feedback loop prevents the unexpected issues, and with everyone is on the same page, through communication apps such as Slack converts the situations in a way allowing you to integrate updates easily, and especially if your team has a large number of daily users.

LambdaTest offers integration with Slack to help you highlight UI issues to your colleague on Slack channels with just a single click.

Conclusion

In the CI/CD methodology, you bake the quality into every step of CI/CD pipeline. Especially, the central feedback loop of Continuous Delivery is a place of constant re-examination to ensure a quality product is being delivered to end-users. Automated tests allow the new features being delivered with bug-free code and expected quality. Project planning for new features involves consideration around analytics, automated testing instrumentation tasks, and performance monitoring.

The entire organization has an important role and should remain focused and incentivized to produce the deliverables with high quality. The role of product managers comes when they need to oversee deployment and quality assurance. The security team should pay attention to the release process. And the major responsibilities of QA team members involved when they test development and staging environments.

All the functions of the QA team should be as much rigor as on production before eventual release. Developers should focus on production release with a detailed investigation. Lastly, choose wisely on the right selection of automation tools. LambdaTest offers 2000+ real browsers along with integrations to CI/CD tools such as Jenkins, Travis CI, and more, to help you incorporate continuous testing in your CI/CD pipeline. Happy testing!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .