Posts Tagged ‘testing’
[NDCOslo2024] No More SQLite: How to Write Tests With EF Core Using TestContainers – Daniel Ward
Amid the arduous arena of application assurance, where integration inspections intersect infrastructure intricacies, Daniel Ward, a .NET navigator and testing tactician, torpedoes the tired trope of SQLite as EF Core’s ersatz examiner. With a penchant for precision and a portfolio of pragmatic patterns, Daniel decries the discrepancies—dialect drifts, devious defaults—that delude developers into dubious dependability. His herald: TestContainers, a titan of transient testing, tethering true-to-type databases to dotnet diagnostics, ensuring examinations echo environments exactly.
Daniel dives direct: SQLite’s siren song—simplicity’s shadow—seduces with speed yet sabotages similitude, spawning spurious successes in schema shadows. Real realms revel in PostgreSQL or SQL Server; sans such sentinels, tests tantalize with triumphs that tumble in truth. His thesis: TestContainers triumphs, turbocharging temporaries—containers conjured cleanly, configured crisply—for credible, containerized corroboration.
Ditching the Decoy: Drawbacks of Database Doppelgangers
SQLite’s shortcomings spotlight starkly: syntax schisms—TOP versus LIMIT—thwart translations; transaction treatments transmute, transactions toggling differently. Daniel details dev database dilemmas: devious dependencies, drift-prone data, deployment drudgery. False flags flourish: tests triumph trivially, only to falter in flight, fostering fragile faith.
His horror stories: SQLite’s solitary schema swallows specifics, sans stored procedures or sequences; in-memory imposters ignore indexes, inflating illusions. Daniel’s decree: discard decoys for doppelgangers divine—TestContainers delivers, Docker-driven duplicates that duplicate dynamics deftly.
Containers as Champions: TestContainers’ Triumphs
TestContainers, Daniel declaims, democratizes diligence: NuGet-nimble, it nurtures nodes—Postgres pods, SQL Server ships—spinning sans setup strife. Benefits burgeon: bit-for-bit fidelity, flakeless flurries, fleet-footed forays. Reusability reigns: withReuse() recycles realms, reining runtime rigorously.
Daniel demos deftly: dotnet add package Testcontainers.PostgreSql; a builder begets a beast, beckoning a bespoke bastion. Connection strings cascade, EF contexts calibrate, tests transact transparently—Respawn resets, restoring rectitude routinely.
Precision in Practice: Pitfalls and Panaceas
Pitfalls persist: parallelism’s pandemonium, port pandemonium—Daniel dispels with Docker Desktop’s discipline, orchestration’s oversight. His heuristic: harness health checks, heed horizons—hundreds hum harmoniously, hovering at half-minutes for hordes.
Respawn’s renaissance: rollback routines, resetting relations rigorously, rectifying residue. Daniel’s distillation: TestContainers transmutes testing from torment to triumph, true tests tempering temper tantrums.
Links:
[PHPForumParis2022] Testing Through OpenAPI, or How to Validate Your Documentation – Stéphane Hulard
Stéphane Hulard, CTO at Chstudio, delivered a compelling session at PHP Forum Paris 2022 on using OpenAPI to validate API documentation. With four years of experience maintaining a PHP-based project, Stéphane shared a practical approach to ensuring documentation aligns with implementation. His talk emphasized the synergy between testing and documentation, offering developers a workflow to enhance collaboration and maintainability in API-driven projects.
The Role of OpenAPI in Documentation
Stéphane introduced OpenAPI as a standardized format for describing APIs, enabling both human-readable documentation and automated testing. He explained how OpenAPI specifications serve as a contract between backend and frontend teams, ensuring consistency. By documenting a single API endpoint, developers can validate its behavior through automated tests, creating a virtuous cycle of reliable documentation and robust code. Stéphane emphasized starting small, documenting one endpoint at a time to build momentum.
Implementing Documentation-Driven Testing
Delving into technical details, Stéphane demonstrated how to integrate OpenAPI with PHP projects, using tools to generate and validate API requests. He shared code examples from Chstudio’s workflow, illustrating how tests derived from OpenAPI specs catch discrepancies early. This approach, akin to Test-Driven Development (TDD), ensures that documentation remains accurate as the codebase evolves. Stéphane highlighted the importance of enriching test suites with edge cases to uncover potential bugs, enhancing overall API reliability.
Enhancing Collaboration Across Teams
Stéphane underscored OpenAPI’s role in fostering collaboration between backend and frontend developers. By defining API contracts upfront, teams can make informed design decisions, reducing miscommunication. He described Chstudio’s experience with a monolithic repository, where OpenAPI facilitated smoother interactions despite the absence of microservices. Stéphane’s approach, which he termed Documentation-Driven Design (DDD), aligns development and documentation efforts, ensuring both are prioritized from the project’s outset.
Encouraging Community Contributions
Concluding, Stéphane invited developers to contribute to open-source OpenAPI tools, emphasizing their accessibility for PHP projects. He encouraged attendees to adopt incremental documentation practices, noting that even partial coverage yields significant benefits. By sharing Chstudio’s workflow, Stéphane inspired developers to integrate OpenAPI into their projects, fostering a culture of disciplined documentation and testing.
Links:
[DevoxxFR2013] Clean JavaScript? Challenge Accepted: Strategies for Maintainable Large-Scale Applications
Lecturer
Romain Linsolas is a Java developer with over two decades of experience, passionate about technical innovation. He has worked at the CNRS on an astrophysics project, as a consultant at Valtech, and as a technical leader at Société Générale. Romain is actively involved in the developpez.com community as a writer and moderator, and he focuses on continuous integration principles to automate and improve team processes. Julien Jakubowski is a consultant and lead developer at OCTO Technology, with a decade of experience helping teams deliver high-quality software efficiently. He co-founded the Ch’ti JUG in Lille and has organized the Agile Tour Lille for two years.
Abstract
This article analyzes Romain Linsolas and Julien Jakubowski’s exploration of evolving JavaScript from rudimentary scripting to robust, large-scale application development. By dissecting historical pitfalls and modern solutions, the discussion evaluates architectural patterns, testing frameworks, and automation tools that enable clean, maintainable code. Contextualized within the shift from server-heavy Java applications to client-side dynamism, the analysis assesses methodologies for avoiding common errors, implications for developer productivity, and challenges in integrating diverse ecosystems. Through practical examples, it illustrates how JavaScript can support complex projects without compromising quality.
Historical Pitfalls and the Evolution of JavaScript Practices
JavaScript’s journey from a supplementary tool in the early 2000s to a cornerstone of modern web applications reflects broader shifts in user expectations and technology. Initially, developers like Romain and Julien used JavaScript for minor enhancements, such as form validations or visual effects, within predominantly Java-based server-side architectures. A typical 2003 example involved inline scripts to check input fields, turning them red on errors and preventing form submission. However, this approach harbored flaws: global namespace pollution from duplicated function names across files, implicit type coercions leading to unexpected concatenations instead of additions (e.g., “100” + 0.19 yielding “1000.19”), and public access to supposedly private variables, breaking encapsulation.
These issues stem from JavaScript’s design quirks, often labeled “dirty” due to surprising behaviors like empty array additions resulting in strings or NaN (Not a Number). Romain’s demonstrations, inspired by Gary Bernhardt’s critiques, highlight arithmetic anomalies where [] + {} equals “[object Object]” but {} + [] yields 0. Such inconsistencies, while entertaining, pose real risks in production code, as seen in scope leakage where loop variables overwrite each other, printing values only 10 times instead of 100.
The proliferation of JavaScript-driven applications, fueled by innovations from Gmail and Google Docs, necessitated more code—potentially 100,000 lines—demanding structured approaches. Early reliance on frameworks like Struts for server logic gave way to client-side demands for offline functionality and instant responsiveness, compelling developers to confront JavaScript’s limitations head-on.
Architectural Patterns for Scalable Code
To tame JavaScript’s chaos, modular architectures inspired by Model-View-Controller (MVC) patterns emerge as key. Frameworks like Backbone.js, AngularJS, and Ember.js facilitate separation of concerns: models handle data, views manage UI, and controllers orchestrate logic. For instance, in a beer store application, an MVC setup might use Backbone to define a Beer model with validation, a BeerView for rendering, and a controller to handle additions.
Modularization via patterns like the Module Pattern encapsulates code, preventing global pollution. A counter example encapsulates a private variable:
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
value: function() {
return privateCounter;
}
};
})();
This ensures privacy, unlike direct access in naive implementations. Advanced libraries like RequireJS implement Asynchronous Module Definition (AMD), loading dependencies on demand to avoid conflicts.
Expressivity is boosted by frameworks like CoffeeScript, which compiles to JavaScript with cleaner syntax, or Underscore.js for functional utilities. Julien’s analogy to appreciating pungent cheese after initial aversion captures the learning curve: mastering these tools reveals JavaScript’s elegance.
Testing and Automation for Reliability
Unit testing, absent in early practices, is now feasible with frameworks like Jasmine, adopting Behavior-Driven Development (BDD). Specs describe behaviors clearly:
describe("Beer addition", function() {
it("should add a beer with valid name", function() {
var beer = new Beer({name: "IPA"});
expect(beer.isValid()).toBe(true);
});
});
Tools like Karma run tests in real browsers, while Istanbul measures coverage. Automation integrates via Maven, Jenkins, or SonarQube, mirroring Java workflows. Violations from JSLint or compilation errors from Google Closure Compiler are flagged, ensuring syntax integrity.
Yeoman, combining Yo (scaffolding), Grunt (task running), and Bower (dependency management), streamlines setup. IDEs like IntelliJ or WebStorm provide seamless support, with Chrome DevTools for debugging.
Ongoing Challenges and Future Implications
Despite advancements, integration remains complex: combining MVC frameworks with testing suites requires careful orchestration, often involving custom recipes. Perennial concerns include framework longevity—Angular vs. Backbone—and team upskilling, demanding substantial training investments.
The implications are profound: clean JavaScript enables scalable, responsive applications, bridging Java developers into full-stack roles. By avoiding pitfalls through patterns and tools, projects achieve maintainability, reducing long-term costs. However, the ecosystem’s youth demands vigilance, as rapid evolutions could obsolete choices.
In conclusion, JavaScript’s transformation empowers developers to tackle ambitious projects confidently, blending familiarity with innovation for superior outcomes.
Links:
[DevoxxBE2012] Re-imagining the Browser with AngularJS
Misko Hevery and Igor Minar, Google engineers and AngularJS co-leads, re-envisioned client-side development. Misko, an Agile coach with open-source contributions, partnered with Igor, focused on developer tools, to showcase AngularJS’s approach to simplifying web apps.
They posited extending the browser with declarative HTML and JavaScript, reducing code while enhancing readability. AngularJS bridges to future standards like web components and model-driven views.
Misko demonstrated data binding, where models sync with views automatically, eliminating manual DOM manipulation. Directives extend HTML, creating custom elements for reusability.
Igor highlighted dependency injection for modularity, and services for shared logic. Routing enables single-page apps, with controllers managing scopes.
They emphasized testability, with built-in mocking and end-to-end testing.
Declarative UI and Data Binding
Misko illustrated two-way binding: changes in models update views, and vice versa, without boilerplate. This declarative paradigm contrasts imperative jQuery-style coding.
Directives like ng-repeat generate lists dynamically, while filters format data.
Modularity and Dependency Management
Igor explained modules encapsulating functionality, injected via DI. This promotes clean, testable code.
Services, factories, and providers offer flexible creation patterns.
Routing and Application Structure
NgRoute handles navigation, loading templates and controllers. Scopes isolate data, with inheritance for hierarchy.
Testing and Future Alignment
Angular’s design facilitates unit and e2e tests, using Karma and Protractor.
They previewed alignment with web components, where directives become custom tags.
In Q&A, they compared to Knockout.js, noting Angular’s framework scope versus library focus.
Misko and Igor’s presentation framed AngularJS as transformative, anticipating browser evolutions while delivering immediate productivity.
Links:
[DevoxxBE2012] Real World Java EE
Adam Bien, a renowned Java consultant, author, and Java Champion with decades of experience in enterprise applications, delivered an impromptu yet insightful session on practical Java EE usage. Adam, known for books like “Real World Java EE Patterns,” shared real-world insights from his freelance projects, emphasizing simplicity and effectiveness over hype.
He started by recounting his journey since 1995, favoring Java EE for its robustness in production. Adam advocated thin WAR deployments, bundling everything into a single archive for easy management, contrasting with complex EAR structures.
Discussing boundaries, Adam promoted domain-driven design, where entities form the core, with services as facades. He cautioned against unnecessary abstractions, like excessive DAOs, favoring direct JPA usage.
Adam highlighted CDI’s power for dependency injection, reducing boilerplate. He demonstrated boundary-control-entity patterns, where boundaries handle transactions, controls manage logic, and entities persist data.
Deployment Strategies and Simplicity
Adam stressed deploying as WARs to containers like GlassFish, avoiding heavy setups. He shared experiences with microservices avant la lettre, using REST for inter-service communication.
He critiqued over-engineering, like misusing ESBs for simple integrations, preferring lightweight approaches.
Testing and Quality Assurance
Adam advocated comprehensive testing: unit with JUnit, integration with Arquillian, and UI with Selenium/Graphene. He demonstrated embedding containers for realistic tests.
He emphasized boundary testing, simulating real scenarios without mocks where possible.
Performance and Scalability
Discussing optimization, Adam noted Java EE’s built-in clustering, but advised measuring first. He shared cases where simple configurations sufficed, avoiding premature scaling.
Community and Best Practices
Adam encouraged open-source contributions, sharing his GitHub projects. He addressed common pitfalls, like session misuse, advocating stateless designs.
In Q&A, he discussed tools like Jenkins for CI and IDEs like IntelliJ.
Adam’s talk reinforced Java EE’s viability for real-world applications through pragmatic, lean practices.
Links:
[DevoxxFR2013] The Space Mountain of Enterprise Java Development
Lecturer
Florent Ramière brings over a decade of software development and project management experience. After years in the US at a software editor and a stint at Capgemini upon returning to France, he co-founded Jaxio with Nicolas Romanetti in 2005. Jaxio offers code generation via Celerio; in 2009, they launched SpringFuse.com, an online version. Active in Paris Java scenes like ParisJUG and Coding Dojos.
Abstract
Florent Ramière’s dynamic demonstration navigates enterprise Java development’s complexities, showcasing tools like Maven, Spring, JPA, and more in a live Eclipse session. Emphasizing practical efficiencies for data-heavy applications, he covers CRUD operations, testing, profiling, and CI. The talk reveals techniques for rapid, robust development, highlighting simplicity’s challenges and offering actionable insights for real-world projects.
Setting the Stage: Tools and Environment for Efficient Development
Ramière begins with audience polling: most work on Java EE/Spring applications involving databases, often exceeding 100 tables. He focuses on large-scale management apps, sharing experiences from consulting across projects.
Demonstrating in Eclipse with Jetty embedded, he launches an internationalized app using an in-memory database for independence. Maven builds the project; SpringFuse aggregates best practices.
Key promise: simplicity is hard; knowing tools accelerates work. If nothing new learned, a Mojito offered – or a fun fact on calculating light speed with chocolate.
The app handles accounts: listing, searching, navigating. CRUD dominates; business logic intersperses.
Core Operations: Querying, Validation, and Data Manipulation
Search uses query-by-example: fields like ‘admin’ or ‘Tokyo’ filter results. JPA with Hibernate enables this; Bean Validation ensures integrity.
Editing involves JSF with PrimeFaces for UI: dialogs, calendars, auto-completes. Commons and Guava libraries aid utilities; Lombok reduces boilerplate.
Saving triggers validations: required fields, formats. Excel exports via JXLS; imports validate before persisting.
Full-text search with Hibernate Search (Lucene) indexes entities, supporting fuzzy matches and facets.
@Entity
@Indexed
public class User {
@Id
private Long id;
@Field(index=Index.YES, analyze=Analyze.YES)
private String name;
// ...
}
This annotates for indexing, enabling advanced queries.
Testing and Quality Assurance: From Unit to Integration
JUnit with Fest-Assert and Mockito tests services: mocking DAOs, verifying behaviors.
Selenium with Firefox automates UI tests: navigating, filling forms, asserting outcomes.
JMeter scripts load tests: threading simulates users, measuring throughput.
Sonar integrates for code reviews: violations, discussions directly in Eclipse.
@Test
public void testService() {
User user = mock(User.class);
when(user.getName()).thenReturn("Test");
assertEquals("Test", service.getUserName(1L));
}
Mockito example for isolated testing.
Performance and Deployment: Profiling and Continuous Integration
JProfiler attaches for heap/thread analysis: identifying leaks, optimizing queries.
Hudson (now Jenkins) builds via Maven: compiling, testing, deploying WARs.
iSpace visualizes dependencies, aiding architecture.
Profiles manage environments: dev/test/prod configurations.
Navigating Complexities: Best Practices and Pitfalls
Ramière advises command-line Maven for reliability; avoid outdated WTP.
For large schemas, tools like SpringFuse generate CRUD, reducing tedium.
NoSQL suits big data, but relational fits structured needs; patterns transfer.
Embrace profiles for configurations; Git for code reviews alongside Sonar/Gerrit.
Impact of profilers on tests: significant, but use for targeted optimizations via thread dumps.
In conclusion, enterprise Java demands tool mastery for efficiency; simplicity emerges from knowledge.