Is API mocking in unit tests important, or does it do nothing? I think the answer is a bit more nuanced, but we do need such tests to reduce daily churn.
DevSecOps is a cultural approach to integrate security in our CI/CD pipeline. It ensures security is implemented on every stage of the SDLC and infrastructure.
How can an attacker exploit leaked credentials? In this new series, we try to answer this question by imagining plausible attack scenarios. Second case: an AWS secret is found in a private repository.
This article will compare the primary security key management services solution use cases among the Azure key vault, AWS KMS, Google CKMS, and other Cloud key management solutions.
Understanding the Metaverse in the world of digital transformation by implementing software testing and quality assurance best practices and techniques.
A closer look at Java at Microsoft and Azure and what Microsoft can offer to modernize existing Java-based apps or bring new ones with the practice of IaC
I'll share some of the most interesting questions, comments from the public, and, of course, the main highlights of the session from the TSQA 2022 Conference.
KEDA is an event-driven autoscaler that horizontally scales a container by adding additional pods based on the number of events needing to be processed.
The article discusses the architectures currently popular for achieving this Serverless Architecture for Scale use cases and how and when we can use them.
In this second part, learn how to centralize IAM for multiple AWS accounts, create and use EC2 instance profiles, and implement just-in-time access with Vault.
Covering the basics of managing AWS IAM with Terraform and learn how to delete the Root/User Access key, enforce MFA, customize password policy, and more.
I have talked about human filters and my plan for digital curation. These items are the fruits of those ideas, the items I deemed worthy from my Google Reader feeds. These items are a combination of tech business news, development news and programming tools and techniques. Making accessible icon buttons (NCZOnline) Double Shot #1097 (A Fresh Cup) Life Beyond Rete – R.I.P Rete 2013 (Java Code Geeks) My Passover Project: Introducing Rattlesnake.CLR (Ayende @ Rahien) Super useful jQuery plugins for responsive web design (HTML5 Zone) Android Development – Your First Steps (Javalobby – The heart of the Java developer community) Never Ever Rewrite Your System (Javalobby – The heart of the Java developer community) Telecommuting, Hoteling, and Managing Product Development (Javalobby – The heart of the Java developer community) The Daily Six Pack: April 1, 2013 (Dirk Strauss) Optimizing Proto-Geeks for Business (DaedTech) Learning Bootstrap Part 2: Working with Buttons (debug mode……) Rumination on Time (Rob Williams' Blog) Unit-Testing Multi-Threaded Code Timers (Architects Zone – Architectural Design Patterns & Best Practices) Metrics for Agile (Javalobby – The heart of the Java developer community) Detecting Java Threads in Deadlock with Groovy and JMX (Inspired by Actual Events) Entrepreneurs: Stop participating in hackathons just to win them (VentureBeat) How to hack the recruitment process to find the best developers for your startup or agency (The Next Web) Hardware Hacks: MongoLab + Arduino (Architects Zone – Architectural Design Patterns & Best Practices) The Daily Six Pack: March 30, 2013 (Dirk Strauss) I hope you enjoy today’s items, and please participate in the discussions on those sites.
A few weeks ago I wrote a blog on synchronizing multithreaded integration tests, which was republished on DZone Javalobby from where it received a comment from Robert Saulnier who quite rightly pointed out that you can also use join() to synchronize a worker thread and its unit tests. This got me thinking, just how many ways can you synchronise multi-threaded integration tests? So, I started counting... and came up with: Using a random delay. Adding a CountDownLatch Thread.join() Acquiring a Semaphore With a Future and ExecutorService Now, I’m not going to explain all the following in great detail, I’ll let the code speak for itself, except to say that all the code samples do roughly the same thing: the unit test creates a ThreadWrapper instance and then calls its doWork() method (or call() in the case of the Future). The unit test’s main thread then waits for the worker thread to complete before asserting that the test has passed. For the sample code demonstrating points 1 and 2 take a look at my original blog on Synchronizing Multithreaded Integration Tests, though I wouldn’t recommend point 1: using a random delay. Thread.join() public class ThreadWrapper { private Thread thread; /** * Start the thread running so that it does some work. */ public void doWork() { thread = new Thread() { /** * Run method adding data to a fictitious database */ @Override public void run() { System.out.println("Start of the thread"); addDataToDB(); System.out.println("End of the thread method"); } private void addDataToDB() { try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } } }; thread.start(); System.out.println("Off and running..."); } /** * Synchronization method. */ public void join() { try { thread.join(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } } public class ThreadWrapperTest { @Test public void testDoWork() throws InterruptedException { ThreadWrapper instance = new ThreadWrapper(); instance.doWork(); instance.join(); boolean result = getResultFromDatabase(); assertTrue(result); } /** * Dummy database method - just return true */ private boolean getResultFromDatabase() { return true; } } Acquiring a Semaphore public class ThreadWrapper { /** * Start the thread running so that it does some work. */ public void doWork() { doWork(null); } @VisibleForTesting void doWork(final Semaphore semaphore) { Thread thread = new Thread() { /** * Run method adding data to a fictitious database */ @Override public void run() { System.out.println("Start of the thread"); addDataToDB(); System.out.println("End of the thread method"); semaphore.release(); } private void addDataToDB() { try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } } }; aquire(semaphore); thread.start(); System.out.println("Off and running..."); } private void aquire(Semaphore semaphore) { try { semaphore.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } } } public class ThreadWrapperTest { @Test public void testDoWork() throws InterruptedException { ThreadWrapper instance = new ThreadWrapper(); Semaphore semaphore = new Semaphore(1); instance.doWork(semaphore); semaphore.acquire(); boolean result = getResultFromDatabase(); assertTrue(result); } /** * Dummy database method - just return true */ private boolean getResultFromDatabase() { return true; } } With a Future public class ThreadWrapper implements Callable { @Override public Boolean call() throws Exception { System.out.println("Start of the thread"); Boolean added = addDataToDB(); System.out.println("End of the thread method"); return added; } /** * Add to the DB and return true if added okay */ private Boolean addDataToDB() { try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } return Boolean.valueOf(true); } } public class ThreadWrapperTest { @Test public void testCall() throws ExecutionException, InterruptedException { ThreadWrapper instance = new ThreadWrapper(); ExecutorService executorService = Executors.newFixedThreadPool(1); Future future = executorService.submit(instance); Boolean result = future.get(); assertTrue(result); } } Having listed all these methods, the next thing to consider is which one is the best? In asking that question you have to define the word “best” in terms of best for what? Best for simplicity? Maintainability? Speed or code size? After all Programming the Art of Making the Right Decision. You may have guessed that I don’t like the random delay idea and prefer the use of a CountDownLatch. Thread.join() is a bit old school; remember that the likes of Semaphore and CountDownLatch were written to improve on the original Java threading techniques. ExecutorService seems a little heavy weight for what we need here. At the end of the day the choice of technique really comes down to personal preference. Finally, I’ve listed five ways of synchronizing multi-threaded integration tests; however, if you can think of any others please let me know... The source code for this blog is available on Github.
Separate out analysis to preserve commit stage processing time The entry point of a Continuous Delivery pipeline is its Commit Stage, and as such manages the compilation, unit testing, analysis, and packaging of source code whenever a change is committed to version control. As the commit stage is responsible for identifying defective code it represents a vital feedback loop for developers, and for that reason Dave Farley and Jez Humble recommend a commit stage that is “ideally less than five minutes and no more than ten” – if the build process is too slow or non-deterministic, the pace of development can soon grind to a halt. Both compilation and unit testing tasks can be optimized for performance, particularly when the commit stage is hosted on a multi-processor Continuous Integration server. Modern compilers require only a few seconds for compilation, and a unit test suite that follows the Michael Feathers strategy of no database/filesystem/network/user interface access should run in parallel in seconds. However, it is more difficult to optimize analysis tasks as they tend to involve third-party tooling reliant upon byte code manipulation. When a significant percentage of commit stage time is consumed by static analysis tooling, it may become necessary to trade-off unit test feedback against static analysis feedback and move the static analysis tooling into a separate Analysis Stage. The analysis stage is triggered by a successful run of the commit stage, and analyses the uploaded artifact(s) and source code in parallel to the acceptance testing stage. If a failure is detected the relevant pipeline metadata is updated and Stop The Line applies. That binary cannot be used elsewhere in the pipeline and further development efforts should cease until the issue is resolved. For example, consider an organisation that has implemented a standard Continuous Delivery pipeline. The commit stage has an average processing time of 5 minutes, of which 1 minute is spent upon static analysis. Over time the codebase grows to the extent that commit stage time increases to 6 minutes, of which 1 minute 30 seconds is spent upon static analysis. With static analysis time growing from 20% to 25% the decision is made to create a separate Analysis stage, which reduces commit time to 4 minutes 30 seconds and improves the developer feedback loop. Static analysis is the definitive example of an automated task that periodically needs human intervention. Regardless of tool choice there will always be a percentage of false positives and false negatives, and therefore a pipeline that implements an Analysis Stage must also offer a capability for an authenticated human user to override prior results for one or more application versions.